Java 重试小工具Retry

该工具只是对Guava中Retryer拙劣的模仿。意在学习其Java8使用方式,代码解耦精髓。

 

package com.fast.cattsoft.util;

import java.util.concurrent.ExecutionException;

public interface RetryResult<V> {

    boolean hasResult();

    boolean hasException();

    V getResult() throws IllegalAccessException;

    V get() throws ExecutionException;

    Throwable getException();

    int getRetryCount();


}
package com.fast.cattsoft.util;

public class SuccessRetryResult<R> implements RetryResult<R> {
    private R result;
    private int tryCount;
    private long intervaTime;

    public SuccessRetryResult(R result, int tryCount, long intervaTime) {
        this.result = result;
        this.tryCount = tryCount;
        this.intervaTime = intervaTime;
    }


    @Override
    public boolean hasResult() {
        return true;
    }

    @Override
    public boolean hasException() {
        return false;
    }

    @Override
    public R getResult() {
        return result;
    }

    @Override
    public R get() {
        return result;
    }

    @Override
    public Throwable getException() {
        return null;
    }

    @Override
    public int getRetryCount() {
        return 0;
    }
}
package com.fast.cattsoft.util;

import java.util.concurrent.ExecutionException;

public class ExceptionRetryResult<R> implements RetryResult<R> {
    private ExecutionException e;
    private int tryCount;
    private long intervaTime;

    ExceptionRetryResult(ExecutionException e, int tryCount, long intervaTime) {
        this.e = e;
        this.tryCount = tryCount;
        this.intervaTime = intervaTime;
    }

    @Override
    public boolean hasResult() {
        return false;
    }

    @Override
    public boolean hasException() {
        return true;
    }

    @Override
    public R getResult() throws IllegalAccessException {
        throw new IllegalAccessException("");
    }

    @Override
    public R get() throws ExecutionException {
        throw e;
    }

    @Override
    public Throwable getException() {
        return e.getCause();
    }

    @Override
    public int getRetryCount() {
        return tryCount;
    }
}
package com.fast.cattsoft.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

public class RetryBuild<V> {
    private List<Predicate<RetryResult<V>>> predicates =
            new ArrayList<Predicate<RetryResult<V>>>(Collections.singleton(new Predicate<RetryResult<V>>() {
                @Override
                public boolean test(RetryResult<V> vRetryResult) {
                    return false;
                }
            }));

    //重试次数
    private int tryCount = 1;

    //每次重试失败后间隔时间
    private long intervaTime = 1;

    public static <V> RetryBuild<V> newBuild() {
        return new RetryBuild<V>();
    }

    public RetryBuild<V> buildTryCount(int tryCount) {
        this.tryCount = tryCount;
        return this;
    }

    public RetryBuild<V> buildIntervaTime(long intervaTime) {
        this.intervaTime = intervaTime;
        return this;
    }

    public RetryBuild<V> buildThrows(Class<? extends Throwable> throwables) {
        predicates.add(new ExceptionClassPredicate<V>(throwables));
        return this;
    }

    public RetryBuild<V> buildResult(Predicate<V> predicate) {
        predicates.add(new SuccessPredicate<V>(predicate));
        return this;
    }

    public Retry<V> build() {

        return new Retry<V>(tryCount, intervaTime, new OnPredicate<V>(predicates));
    }

}

class ExceptionClassPredicate<V> implements Predicate<RetryResult<V>> {
    private Class<? extends Throwable> exception;

    public ExceptionClassPredicate(Class<? extends Throwable> exception) {
        this.exception = exception;
    }

    @Override
    public boolean test(RetryResult<V> vRetryResult) {
        if (!vRetryResult.hasException()) {
            return false;
        }
        return exception.isAssignableFrom(vRetryResult.getException().getClass());
    }
}

class SuccessPredicate<V> implements Predicate<RetryResult<V>> {
    private Predicate<V> delegate;

    public SuccessPredicate(Predicate<V> predicate) {
        this.delegate = predicate;
    }

    @Override
    public boolean test(RetryResult<V> vRetryResult) {
        if (!vRetryResult.hasResult()) {
            return false;
        }
        try {
            V result = vRetryResult.getResult();
            boolean test = delegate.test(result);
            return test;
        } catch (Exception e) {
            throw new RuntimeException("");
        }
    }
}

class ExceptionPredicate<V> implements Predicate<RetryResult<V>> {
    private Predicate<Throwable> delegate;

    public ExceptionPredicate(Predicate<Throwable> delegate) {
        this.delegate = delegate;
    }

    @Override
    public boolean test(RetryResult<V> vRetryResult) {
        if (!vRetryResult.hasException()) {
            return false;
        }
        return delegate.test(vRetryResult.getException());
    }
}

class OnPredicate<V> implements Predicate<RetryResult<V>> {

    //private List<? extends Predicate<? super V>> predicates;
    private List<Predicate<RetryResult<V>>> predicates;

    public OnPredicate(List<Predicate<RetryResult<V>>> predicates) {
        this.predicates = predicates;
    }

    @Override
    public boolean test(RetryResult<V> vRetryResult) {
        for (int i = 0; i < predicates.size(); i++) {
            if (predicates.get(i).test(vRetryResult)) {
                return true;
            }
        }
        return false;
    }
}


package com.fast.cattsoft.util;

import com.github.rholder.retry.*;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestClientException;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 重试工具类
 *
 * @param <V>
 */
public class Retry<V> {

    //重试次数
    private int tryCount = 1;

    //每次重试失败后间隔时间
    private long intervaTime = 1;

    private Predicate<RetryResult<V>> predicate;

    public Retry(int tryCount, long intervaTime, Predicate<RetryResult<V>> predicate) {
        this.tryCount = tryCount;
        this.intervaTime = intervaTime;
        this.predicate = predicate;
    }


    public V call(Supplier<V> supplier) throws ExecutionException {
        int currTryCount = 0;
        for (int i = 0; ; i++) {
            RetryResult<V> retryResult;
            try {
                V result = supplier.get();
                retryResult = new SuccessRetryResult(result, tryCount, intervaTime);
            } catch (Exception e) {
                retryResult =
                        new ExceptionRetryResult(new ExecutionException(e), tryCount, intervaTime);
            } finally {
                currTryCount++;
            }

            if (!predicate.test(retryResult)) {
                return retryResult.get();
            }
            if (currTryCount >= this.tryCount) {
                throw new RuntimeException("retry number more than " + this.tryCount);
            } else {
                try {
                    Thread.sleep(this.intervaTime);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("");
                }
            }
        }
    }


    public static void main(String[] args) throws Throwable {
        customReTry();
        //guavaRetry();
    }

    public static void customReTry() throws Throwable {
        Retry<Integer> build = RetryBuild.<Integer>newBuild()
                .buildTryCount(3)
                .buildIntervaTime(2000l)
                .buildResult(res -> {
                    System.out.println("result has to than " + 6);
                    return res > 6;
                })
                .buildThrows(ArithmeticException.class)
                .build();
        Integer call = build.call(() -> {
            int i = 0;
            //int b = 4 / i;
            return 5;
        });
        System.out.println("result :" + call);

    }

    //可以参考guava重试代码
    public static void guavaRetry() throws ExecutionException, RetryException {
        new ArrayList<>(1);
        Retryer<Integer> build = RetryerBuilder.<Integer>newBuilder()
                //  .retryIfException(e -> e.getMessage().contains(""))
                .retryIfResult(e -> {
                    System.out.println("result has to than 5");
                    return e > 5;
                })
                .retryIfExceptionOfType(ArithmeticException.class)
                .withStopStrategy(StopStrategies.stopAfterAttempt(1))
                .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))
                .build();
        Integer call = build.call(() -> {
            int i = 0;
            //int b = 4 / i;
            return 5;
        });
        System.out.println("result :" + call);
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值