发布时间:2020-12-09作者:laosun阅读(1967)
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) - 执行失败===>
版权属于: 技术客
原文地址: https://www.sunjs.com/article/detail/7792b43295f046628620b729a0052eae.html
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。