工具类:

import java.lang.reflect.Method;

public class RetryUtil {
private static ThreadLocal<Integer> retryTimesInThread = new ThreadLocal<>(); /**
* 设置当前方法重试次数
*
* @param retryTimes
* @return
*/
public static RetryUtil setRetryTimes(Integer retryTimes) {
if (retryTimesInThread.get() == null)
retryTimesInThread.set(retryTimes);
return new RetryUtil();
} /**
* 重试当前方法
* <p>按顺序传入调用者方法的所有参数</p>
* @param args
* @return
*/
public Object retry(Object... args) {
try {
Integer retryTimes = retryTimesInThread.get();
if (retryTimes <= 0) {
retryTimesInThread.remove();
return null;
}
retryTimesInThread.set(--retryTimes);
String upperClassName = Thread.currentThread().getStackTrace()[2].getClassName();
String upperMethodName = Thread.currentThread().getStackTrace()[2].getMethodName(); Class clazz = Class.forName(upperClassName);
Object targetObject = clazz.newInstance();
Method targetMethod = null;
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals(upperMethodName)) {
targetMethod = method;
break;
}
}
if (targetMethod == null)
return null;
targetMethod.setAccessible(true);
return targetMethod.invoke(targetObject, args);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
调用:
RetryUtil.setRetryTimes(3).retry(url, workOrderPost);

为了防止多线程情况下出现并发问题,这里定义了一个 ThreadLocal 变量来存储当前线程的重试次数。然后通过 setRetryTimes ,一个静态方法来设置这个重试次数,并返回一个 RetryUtil 对象。

调用者通过返回的 RetryUtil 对象调用 retry 方法实现重试。retry 方法接收一个可变参数,因为调用者实际的参数不确定,这里要求按顺序传入调用者方法的所有参数。

接下来判断 ThreadLocal 变量是否小于等于 0 ,如果是,则说明重复次数已达到,返回 null;如果不是,则让 ThreadLocal 变量减一。接下来:

String upperClassName = Thread.currentThread().getStackTrace()[2].getClassName();
String upperMethodName = Thread.currentThread().getStackTrace()[2].getMethodName();

来获取当前方法(retry)的上层方法名和上层类名。Thread.currentThread().getStackTrace() 得到线程的方法栈数组,数组的第二个元素 Thread.currentThread().getStackTrace() [1]  为当前方法栈,第三个元素 Thread.currentThread().getStackTrace() [2] 为上层方法栈,通过上层方法的栈帧得到上层方法的方法名和类名。

下面就是通过反射获取该类的所有方法,循环判断方法名是否等于所要重复执行的方法,如果是的话,执行该方法,参数就是传入可变参数。

注意睡眠重试确保之前操作事务提交,避免超时。

最新文章

  1. 初学Python
  2. Tensorflow 实现稠密输入数据的逻辑回归二分类
  3. Eclipse修改编码格式
  4. php7.0支持调用lua脚本
  5. adb获取不了设备List of devices attached
  6. 启用VTX技术支持启动android的虚拟机 - 报错
  7. Rotate List 面试题
  8. Android自定义控件(四)——让每一个Activity UI都具有弹性
  9. java和C#之间SOCKET通信的问题
  10. Good Luck Charlie(听力恢复训练)
  11. js数据转换
  12. Linux 学习笔记_12_文件共享服务_3_NFS网络文件服务
  13. PHP全栈学习笔记10
  14. 定义一个Collection接口类型的变量,引用一个Set集合的实现类,实现添加单个元素, 添加另一个集合,删除元素,判断集合中是否包含一个元素, 判断是否为空,清除集合, 返回集合里元素的个数等常用操作。
  15. Linux怎么安装vim编译器
  16. zeppelin中运行spark streaming kakfa &amp; 实时可视化
  17. mysql Communication link failure, message from server: &quot;Can&#39;t get hostname for your address&quot;
  18. 美秒快报 移动端API接口后台制作总结
  19. sql ltrim/rtrim 字段中为中文时出现?的问题
  20. pytest文档18-配置文件pytest.ini

热门文章

  1. 编程哲学之C#篇:01——创世纪
  2. Java基础学习篇---------String、集合的学习
  3. Comparable接口——容器中自定义类排序
  4. 六,apache修改默认根文件路径
  5. webpack快速入门——配置文件:入口和出口,多入口、多出口配置
  6. [AIR] StageWebView可以和js通信
  7. CDN添加流程
  8. 如何在for循环中使用多线程
  9. js有关数组的函数
  10. centos7无法上网问题