您的位置 首页 java

Java 自制重试机制(通用的异常重试工具类)

异常重试机制/重试工具类,直接上代码

 import java.util.Arrays;
 
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * 异常重试机制/重试工具类
 *
 * @Author: sun
 * @Date: 2020-12-08 16:40
 */public abstract class RetryWrap<T> {
 
    private static final Logger logger = LoggerFactory.getLogger(RetryWrap.class);
 
    private static final String taskName = "重试机制";
 
    private String threadName;// 自定义线程名称
    private int maxAttempts = 3; // 重试次数,默认3
    private int nowAttempts = 0; // 当前重试次数,默认0
    private long delay = 1000L; // 隔多少毫秒后重试,默认为1000L(1秒)
    private double multiplier; // 延迟的倍数,比如delay=1000L,multiplier=2时,第一次重试为1秒后,第二次为2秒,第三次为4秒
 
    public T execute() throws Exception {
        long preSleepTime = 0L;
        for (int i = 0; i <= maxAttempts; i++) {// 第0次请求表示首次执行,并非重试
            this.nowAttempts = i;
            try {
                if (i != 0) {
                    logger.info(append(taskName, threadName, preSleepTime + " 毫秒后准备第 " + i + " 次重试"));
                    Thread.sleep(preSleepTime);
                } else {
                    logger.info(append(taskName, threadName, "进入队列,首次执行"));
                }
                T result = todo();// 执行
                if (i != 0) {
                    logger.info(append(taskName, threadName, "第 " + i + " 次重试执行已成功"));
                } else {
                    logger.info(append(taskName, threadName, "首次执行已成功"));
                }
                return result;
            } catch (Exception e) {
                e.printStackTrace();
                if (i == 0) {
                    logger.error(append(taskName, threadName, "首次执行", "出现异常", e.getMessage()));
                    preSleepTime = getDelay();
                } else if (i == maxAttempts) {
                    logger.error(append(taskName, threadName, "第 " + i + " 次重试", "出现异常", e.getMessage()));
                    // 最后一次循环,将异常抛出
                    throw e;
                } else {
                    logger.error(append(taskName, threadName, "第 " + i + " 次重试", "出现异常", e.getMessage()));
                    Double d = preSleepTime * getMultiplier();
                    preSleepTime = d.longValue();
                }
            }
        }
        return null;
    }
 
    /**
     * 钩子
     */    protected abstract T todo() throws Exception;
 
    /**
     * 日志输出美化
     */    private String append(Object... params) {
        return StringUtils.join(Arrays.asList(params).toArray(), "===>");
    }
 
    public int getMaxAttempts() {
        return maxAttempts;
    }
 
    public RetryWrap<T> setMaxAttempts(int maxAttempts) {
        this.maxAttempts = maxAttempts;
        this.nowAttempts = maxAttempts;
        return this;
    }
 
    public int getNowAttempts() {
        return nowAttempts;
    }
 
    public long getDelay() {
        return delay;
    }
 
    public RetryWrap<T> setDelay(long delay) {
        this.delay = delay;
        return this;
    }
 
    public double getMultiplier() {
        return multiplier;
    }
 
    public RetryWrap<T> setMultiplier(double multiplier) {
        this.multiplier = multiplier;
        return this;
    }
 
    public String getThreadName() {
        return threadName;
    }
 
    public RetryWrap<T> setThreadName(String threadName) {
        this.threadName = threadName;
        return this;
    }
 
    /**
     * 测试案例
     * 
     * @param args
     */    public static void main(String[] args) {
        String result = null;
        try {
            result = new RetryWrap<String>() {
                @Override
                protected String todo() throws Exception {
                    int nowAttempts = this.getNowAttempts();
                    if (nowAttempts != 4) {// 重试三次都执行失败的测试
//                  if (nowAttempts != 3) {// 最后一次重试执行成功的测试
//                      Integer.valueOf("a");//运行时异常
                        throw new NullPointerException();// 非运行时程序异常,也有可能根据逻辑判断手动抛出自定义异常
                    }
                    return "SUCCESS";
                }
            }.setMaxAttempts(3).setDelay(1000L).setMultiplier(2).setThreadName("测试").execute();
            logger.info("执行成功,跳出重试机制,打印执行结果", result);
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("执行失败", e.getMessage());
        }
    }
 
}  

模拟执行,让最后一次重试执行成功,打印如下:

 15:01:16.003 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:36) - 重试机制===>测试===>进入队列,首次执行
java.lang.NullPointerException
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:86)
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:1)
    at com.xxxx.demo.RetryWrap.execute(RetryWrap.java:38)
    at com.xxxx.demo.RetryWrap.main(RetryWrap.java:90)
15:01:16.020 [ERROR][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:48) - 重试机制===>测试===>首次执行===>出现异常===>
15:01:16.021 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:33) - 重试机制===>测试===>1000 毫秒后准备第 1 次重试
java.lang.NullPointerException
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:86)
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:1)
    at com.xxxx.demo.RetryWrap.execute(RetryWrap.java:38)
    at com.xxxx.demo.RetryWrap.main(RetryWrap.java:90)
15:01:17.024 [ERROR][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:55) - 重试机制===>测试===>第 1 次重试===>出现异常===>
15:01:17.025 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:33) - 重试机制===>测试===>2000 毫秒后准备第 2 次重试
java.lang.NullPointerException
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:86)
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:1)
    at com.xxxx.demo.RetryWrap.execute(RetryWrap.java:38)
    at com.xxxx.demo.RetryWrap.main(RetryWrap.java:90)
15:01:19.030 [ERROR][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:55) - 重试机制===>测试===>第 2 次重试===>出现异常===>
15:01:19.031 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:33) - 重试机制===>测试===>4000 毫秒后准备第 3 次重试
15:01:23.035 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:40) - 重试机制===>测试===>第 3 次重试执行已成功
15:01:23.035 [INFO][main] com.xxxx.demo.RetryWrap.main(RetryWrap.java:91) - 执行成功,跳出重试机制,打印执行结果===>SUCCESS  

屏蔽main方法中的throw new NullPointerException(); 表示首次执行就成功,打印如下:

 15:05:19.447 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:36) - 重试机制===>测试===>进入队列,首次执行
15:05:19.452 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:42) - 重试机制===>测试===>首次执行已成功
15:05:19.456 [INFO][main] com.xxxx.demo.RetryWrap.main(RetryWrap.java:91) - 执行成功,跳出重试机制,打印执行结果===>SUCCESS  

重试全部都执行失败的情况下打印如下:

 15:07:55.487 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:36) - 重试机制===>测试===>进入队列,首次执行
java.lang.NullPointerException
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:86)
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:1)
    at com.xxxx.demo.RetryWrap.execute(RetryWrap.java:38)
    at com.xxxx.demo.RetryWrap.main(RetryWrap.java:90)
15:07:55.504 [ERROR][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:48) - 重试机制===>测试===>首次执行===>出现异常===>
15:07:55.504 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:33) - 重试机制===>测试===>1000 毫秒后准备第 1 次重试
java.lang.NullPointerException
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:86)
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:1)
    at com.xxxx.demo.RetryWrap.execute(RetryWrap.java:38)
    at com.xxxx.demo.RetryWrap.main(RetryWrap.java:90)
15:07:56.509 [ERROR][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:55) - 重试机制===>测试===>第 1 次重试===>出现异常===>
15:07:56.509 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:33) - 重试机制===>测试===>2000 毫秒后准备第 2 次重试
java.lang.NullPointerException
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:86)
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:1)
    at com.xxxx.demo.RetryWrap.execute(RetryWrap.java:38)
    at com.xxxx.demo.RetryWrap.main(RetryWrap.java:90)
15:07:58.510 [ERROR][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:55) - 重试机制===>测试===>第 2 次重试===>出现异常===>
15:07:58.511 [INFO][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:33) - 重试机制===>测试===>4000 毫秒后准备第 3 次重试
java.lang.NullPointerException
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:86)
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:1)
    at com.xxxx.demo.RetryWrap.execute(RetryWrap.java:38)
    at com.xxxx.demo.RetryWrap.main(RetryWrap.java:90)
15:08:02.516 [ERROR][main] com.xxxx.demo.RetryWrap.execute(RetryWrap.java:51) - 重试机制===>测试===>第 3 次重试===>出现异常===>
java.lang.NullPointerException
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:86)
    at com.xxxx.demo.RetryWrap$1.todo(RetryWrap.java:1)
    at com.xxxx.demo.RetryWrap.execute(RetryWrap.java:38)
    at com.xxxx.demo.RetryWrap.main(RetryWrap.java:90)
15:08:02.517 [INFO][main] com.xxxx.demo.RetryWrap.main(RetryWrap.java:94) - 执行失败===>  

文章来源:智云一二三科技

文章标题:Java 自制重试机制(通用的异常重试工具类)

文章地址:https://www.zhihuclub.com/176268.shtml

关于作者: 智云科技

热门文章

网站地图