Java一个简单的重试工具包
在接口调用中由于各种原因,可能会重置失败的任务,使用Guava-Retrying可以方便的实现重试功能。
首先,需要引用Guava-Retrying的包
- <dependency>
<groupId>com.github.rholder</groupId>
<artifactId>guava-retrying</artifactId>
<version>2.0.0</version>
</dependency>
代码示例:
- import com.github.rholder.retry.Retryer;
- import com.github.rholder.retry.RetryerBuilder;
- import com.github.rholder.retry.StopStrategies;
- import com.google.common.base.Predicates;
- import java.util.concurrent.TimeUnit;
- import static com.github.rholder.retry.WaitStrategies.incrementingWait;
- /**
- * @author wangxuexing
- * @descrption
- * @date
- */
- public class RetryDemo {
- public static void main(String[] args) {
- Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder().
- //如果异常会重试
- retryIfException().
- //如果结果为false会重试
- retryIfResult(Predicates.equalTo(false)).
- //重调策略
- withWaitStrategy(incrementingWait(30, TimeUnit.SECONDS, 30, TimeUnit.SECONDS)).
- //尝试次数
- withStopStrategy(StopStrategies.stopAfterAttempt(3)).
- //注册监听
- withRetryListener(new MyRetryListener()).build();
- try {
- retryer.call(new TaskCallable());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
其中TaskCallable是任务的具体实现类,它实现了Callable接口
- import java.util.concurrent.Callable;
- /**
- * @author wangxuexing
- * @descrption
- * @date
- */
- public class TaskCallable implements Callable<Boolean> {
- public Boolean call() throws Exception {
- return false;
- }
- }
- 另外,MyRetryListener监听实现了RetryListener接口,每次重试都会回调注册的监听
- import com.github.rholder.retry.Attempt;
- import com.github.rholder.retry.RetryListener;
- /**
- * @author wangxuexing
- * @descrption
- * @date
- */
- public class MyRetryListener implements RetryListener {
- public <V> void onRetry(Attempt<V> attempt) {
- System.out.print("[retry]time=" + attempt.getAttemptNumber());
- // 距离第一次重试的延迟
- System.out.print(",delay=" + attempt.getDelaySinceFirstAttempt());
- // 重试结果: 是异常终止, 还是正常返回
- System.out.print(",hasException=" + attempt.hasException());
- System.out.print(",hasResult=" + attempt.hasResult());
- // 是什么原因导致异常
- if (attempt.hasException()) {
- System.out.print(",causeBy=" + attempt.getExceptionCause().toString());
- } else {// 正常返回时的结果
- System.out.print(",result=" + attempt.getResult());
- }
- System.out.println();
- }
- }
执行一下main方法,可以看到执行的结果:
- [retry]time=1,delay=0,hasException=false,hasResult=true,result=false
- [retry]time=2,delay=30000,hasException=false,hasResult=true,result=false
- [retry]time=3,delay=90000,hasException=false,hasResult=true,result=false
- com.github.rholder.retry.RetryException: Retrying failed to complete successfully after 3 attempts.
- at com.github.rholder.retry.Retryer.call(Retryer.java:174)
- at test.retryer.RetryDemo.main(RetryDemo.java:32)
下面详细分析一下:
RetryerBuilder是一个factory创建者,可以定制设置重试源且可以支持多个重试源,可以配置重试次数或重试超时时间,以及可以配置等待时间间隔,创建重试者Retryer实例。
RetryerBuilder的重试源支持Exception异常对象 和自定义断言对象,通过retryIfException 和retryIfResult设置,同时支持多个且能兼容。
retryIfException,抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
retryIfRuntimeException只会在抛runtime异常的时候才重试,checked异常和error都不重试。
retryIfExceptionOfType允许我们只在发生特定异常的时候才重试,比如NullPointerException和IllegalStateException都属于runtime异常,也包括自定义的error
retryIfResult可以指定你的Callable方法在返回值的时候进行重试
StopStrategy:停止重试策略,提供三种:
StopAfterDelayStrategy 设定一个最长允许的执行时间;比如设定最长执行10s,无论任务执行次数,只要重试的时候超出了最长时间,则任务终止,并返回重试异常RetryException。
NeverStopStrategy 不停止,用于需要一直轮训知道返回期望结果的情况。
StopAfterAttemptStrategy 设定最大重试次数,如果超出最大重试次数则停止重试,并返回重试异常。
WaitStrategy:等待时长策略(控制时间间隔),返回结果为下次执行时长:
FixedWaitStrategy 固定等待时长策略。
RandomWaitStrategy 随机等待时长策略(可以提供一个最小和最大时长,等待时长为其区间随机值)。
IncrementingWaitStrategy 递增等待时长策略(提供一个初始值和步长,等待时间随重试次数增加而增加)。
ExponentialWaitStrategy 指数等待时长策略。
FibonacciWaitStrategy Fibonacci 等待时长策略。
ExceptionWaitStrategy 异常时长等待策略。
CompositeWaitStrategy 复合时长等待策略。
Java一个简单的重试工具包的更多相关文章
- Java一个简单的贪吃蛇
Java一个简单的贪吃蛇 虽然GUI已经要淘汰了,但是手动写写界面还是有助于理解语法的,像构造函数 ,函数调用,内部类,继承,接口.有助于半初学者强化理解. 直接上代码 游戏主体类: package ...
- java一个简单的管理系统
用java实现的简单管理系统 运行出来的状态 实现了新增.删除.借出.归还.排行榜简单的功能! 下面是简单的代码 首先定义一个书籍类,自己打开哦! public class Book implemen ...
- Java一个简单的线程池实现
线程池代码 import java.util.List; import java.util.Vector; public class ThreadPool { private static ...
- Java一个简单的文件工具集
class FileUtils { //文件目录下文件总数目 public static int fileNumber(File dir) { int filenumber = 0; if(dir.e ...
- 一个简单的Java死锁示例(转)
在实际编程中,要尽量避免出现死锁的情况,但是让你故意写一个死锁的程序时似乎也不太简单(有公司会出这样的面试题),以下是一个简单的死锁例子,程序说明都写着类的注释里了,有点罗嗦,但是应该也还是表述清楚了 ...
- 从一个简单的Java单例示例谈谈并发
一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static Un ...
- 从一个简单的Java单例示例谈谈并发 JMM JUC
原文: http://www.open-open.com/lib/view/open1462871898428.html 一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这 ...
- 手把手教你用redis实现一个简单的mq消息队列(java)
众所周知,消息队列是应用系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有 ActiveMQ,RabbitMQ,Zero ...
- 一个简单的Java web服务器实现
前言 一个简单的Java web服务器实现,比较简单,基于java.net.Socket和java.net.ServerSocket实现: 程序执行步骤 创建一个ServerSocket对象: 调用S ...
随机推荐
- Spring源码系列 — BeanDefinition扩展点
前言 前文介绍了Spring Bean的生命周期,也算是XML IOC系列的完结.但是Spring的博大精深,还有很多盲点需要摸索.整合前面的系列文章,从Resource到BeanDefinition ...
- 使用Python+Selenium模拟登录QQ空间
使用Python+Selenium模拟登录QQ空间爬QQ空间之类的页面时大多需要进行登录,研究QQ登录规则的话,得分析大量Javascript的加密解密,这绝对能掉好几斤头发.而现在有了seleniu ...
- python 父类方法中使用不同的子类中的不同类对象
# coding:utf-8 class Animal(object): def __init__(self): self._name = None self._f = None def eat(se ...
- SpringCloud框架
最近一直在针对SpringCloud框架做项目,从中踩了不少的坑,也渐渐梳理出了一些内容,由于SpringCloud作为一个全家桶,其中东西太多,所以这时候就要有所取舍,这里就想把自己比较常用组件及架 ...
- Java获取客户端真实IP地址
Java代码 import javax.servlet.http.HttpServletRequest; /** * 获取对象的IP地址等信息 */ public class IPUtil { /** ...
- php字符串查找函数 php查找字符串中出现的次数函数substr_count,判断字符串中是否包含另一个字符串函数strpos
php字符串查找函数 php查找字符串中出现的次数函数substr_count,判断字符串中是否包含另一个字符串函数strpossubstr_count($haystack, $needle [,$o ...
- 了解iOS各个版本新特性总结
参考了一下的文章:https://blog.csdn.net/zxtc19920/article/details/54341836 iOS7新特性 · 在iOS7当中,使用麦克风也需要取得用户同意了. ...
- visudo: /etc/sudoers is busy, try again later
启动visudo时,报错"visudo: /etc/sudoers is busy, try again later" 解决思路:杀掉visudo进程 ps -ef|grep vi ...
- [TCP/IP] 关闭连接后为什么客户端最后还要等待2MSL
MSL(Maximum Segment Lifetime)报文最大生存时间,2MSL即两倍的MSL,TCP允许不同的实现可以设置不同的MSL值. 第一,保证客户端发送的最后一个ACK报文能够到达服务器 ...
- Nginx内置变量以及日志格式变量
$args #请求中的参数值$query_string #同 $args$arg_NAME #GET请求中NAME的值$is_args #如果请求中有参数,值为"?",否则为空字符 ...