Java基于Guava Retrying實現(xiàn)重試功能
在接口調(diào)用中由于各種原因,可能會重置失敗的任務(wù),使用Guava-Retrying可以方便的實現(xiàn)重試功能。
首先,需要引用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(). //如果結(jié)果為false會重試 retryIfResult(Predicates.equalTo(false)). //重調(diào)策略 withWaitStrategy(incrementingWait(30, TimeUnit.SECONDS, 30, TimeUnit.SECONDS)). //嘗試次數(shù) withStopStrategy(StopStrategies.stopAfterAttempt(3)). //注冊監(jiān)聽 withRetryListener(new MyRetryListener()).build(); try { retryer.call(new TaskCallable()); } catch (Exception e) { e.printStackTrace(); } } }
其中TaskCallable是任務(wù)的具體實現(xiàn)類,它實現(xiàn)了Callable接口
import java.util.concurrent.Callable; /** * @author wangxuexing * @descrption * @date */ public class TaskCallable implements Callable<Boolean> { public Boolean call() throws Exception { return false; } }
另外,MyRetryListener監(jiān)聽實現(xiàn)了RetryListener接口,每次重試都會回調(diào)注冊的監(jiān)聽
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()); // 重試結(jié)果: 是異常終止, 還是正常返回 System.out.print(",hasException=" + attempt.hasException()); System.out.print(",hasResult=" + attempt.hasResult()); // 是什么原因?qū)е庐惓? if (attempt.hasException()) { System.out.print(",causeBy=" + attempt.getExceptionCause().toString()); } else {// 正常返回時的結(jié)果 System.out.print(",result=" + attempt.getResult()); } System.out.println(); } }
執(zhí)行一下main方法,可以看到執(zhí)行的結(jié)果:
[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創(chuàng)建者,可以定制設(shè)置重試源且可以支持多個重試源,可以配置重試次數(shù)或重試超時時間,以及可以配置等待時間間隔,創(chuàng)建重試者Retryer實例。
- RetryerBuilder的重試源支持Exception異常對象 和自定義斷言對象,通過retryIfException 和retryIfResult設(shè)置,同時支持多個且能兼容。
- retryIfException,拋出runtime異常、checked異常時都會重試,但是拋出error不會重試。
- retryIfRuntimeException只會在拋runtime異常的時候才重試,checked異常和error都不重試。
- retryIfExceptionOfType允許我們只在發(fā)生特定異常的時候才重試,比如NullPointerException和IllegalStateException都屬于runtime異常,也包括自定義的error
- retryIfResult可以指定你的Callable方法在返回值的時候進行重試
StopStrategy:停止重試策略,提供三種:
StopAfterDelayStrategy 設(shè)定一個最長允許的執(zhí)行時間;比如設(shè)定最長執(zhí)行10s,無論任務(wù)執(zhí)行次數(shù),只要重試的時候超出了最長時間,則任務(wù)終止,并返回重試異常RetryException。
NeverStopStrategy 不停止,用于需要一直輪訓(xùn)知道返回期望結(jié)果的情況。
StopAfterAttemptStrategy 設(shè)定最大重試次數(shù),如果超出最大重試次數(shù)則停止重試,并返回重試異常。
- WaitStrategy:等待時長策略(控制時間間隔),返回結(jié)果為下次執(zhí)行時長:
- FixedWaitStrategy 固定等待時長策略。
- RandomWaitStrategy 隨機等待時長策略(可以提供一個最小和最大時長,等待時長為其區(qū)間隨機值)。
- IncrementingWaitStrategy 遞增等待時長策略(提供一個初始值和步長,等待時間隨重試次數(shù)增加而增加)。
- ExponentialWaitStrategy 指數(shù)等待時長策略。
- FibonacciWaitStrategy Fibonacci 等待時長策略。
- ExceptionWaitStrategy 異常時長等待策略。
- CompositeWaitStrategy 復(fù)合時長等待策略。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot Maven打包跳過測試的五種方式小結(jié)
本文主要介紹了Springboot Maven打包跳過測試的五種方式小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04關(guān)于Java Spring三級緩存和循環(huán)依賴的深入理解
對于循環(huán)依賴,我相信讀者無論只是聽過也好,還是有過了解也好,至少都有所接觸。但是我發(fā)現(xiàn)目前許多博客對于循環(huán)依賴的講解并不清楚,都提到了Spring的循環(huán)依賴解決方案是三級緩存,但是三級緩存每一級的作用是什么,很多博客都沒有提到,本篇文章帶你深入了解2021-09-09java 字符串內(nèi)存分配的分析與總結(jié)(推薦)
下面小編就為大家?guī)硪黄猨ava 字符串內(nèi)存分配的分析與總結(jié)(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-08-08淺談System.getenv()和System.getProperty()的區(qū)別
這篇文章主要介紹了System.getenv()和System.getProperty()的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06MybatisPlus查詢數(shù)據(jù)日期格式化問題解決方法
MyBatisPlus是MyBatis的增強工具,支持常規(guī)的CRUD操作以及復(fù)雜的聯(lián)表查詢等功能,這篇文章主要給大家介紹了關(guān)于MybatisPlus查詢數(shù)據(jù)日期格式化問題的解決方法,需要的朋友可以參考下2023-10-10MyBatis中的XML實現(xiàn)和動態(tài)SQL實現(xiàn)示例詳解
這篇文章主要介紹了MyBatis中的XML實現(xiàn)和動態(tài)SQL實現(xiàn),我們可以將XML中重復(fù)出現(xiàn)的內(nèi)容提取出來放到sql標簽中,當需要用到sql標簽中的內(nèi)容時,用include標簽將sql標簽中的內(nèi)容引進來即可,感興趣的朋友跟隨小編一起看看吧2024-02-02