在接口調用中由於各種原因,可能會重置失敗的任務,使用Guava-Retrying可以方便的實現重試功能。
首先,需要引用Guava-Retrying的包
<dependency>
<groupId>com.github.rholder</groupId>
<artifactId>guava-retrying</artifactId>
<version>2.0.0</version>
</dependency>
代碼示例:
public class RetryDemo {
public static void main(String[] args) {
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder().
//如果異常會重試
retryIfException().
//如果結果爲false會重試
retryIfResult(Predicates.equalTo(false)).
//重調策略
withWaitStrategy(WaitStrategies.fixedWait(10, TimeUnit.SECONDS)).
//嘗試次數
withStopStrategy(StopStrategies.stopAfterAttempt(3)).
//註冊監聽
withRetryListener(new MyRetryListener()).build();
try {
retryer.call(new TaskCallable());
} catch (Exception e) {
e.printStackTrace();
}
}
}
其中TaskCallable是任務的具體實現類,它實現了Callable接口
public class TaskCallable implements Callable<Boolean>{
public Boolean call() throws Exception {
return false;
}
}
另外,MyRetryListener監聽實現了RetryListener接口,每次重試都會回調註冊的監聽
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=10001,hasException=false,hasResult=true,result=false
[retry]time=3,delay=20002,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 org.thinking.java.base.guava.retrying.RetryDemo.main(RetryDemo.java:26)
下面詳細分析一下:
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 複合時長等待策略。