在實際開發中咱們常常會遇到須要輪詢查詢一個接果,實現輪詢的方式有不少種,咱們常常要寫許多代碼,有時還會怕寫出的代碼有bug,若是已經有輪子了,咱們就不必重複造輪子了,畢竟時間有限,咱們要掙錢。java
github上開源的重試利器: https://github.com/rholder/guava-retryinggit
此retry是結合了Callable接口來實現,重試功能的,話很少說,直接上碼。github
<dependency> <groupId>com.github.rholder</groupId> <artifactId>guava-retrying</artifactId> <version>2.0.0</version> </dependency>
1.若是想重試幾回就結束輪詢的話,可參考以下代碼算法
package com.example.guava; import com.github.rholder.retry.RetryException; 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.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; /** * @author: GuanBin * @date: Created in 下午4:30 2019/11/3 */ public class RetryTest { public static void main(String[] args) { //callable是定義具體的業務操做,並返回該操做結果的返回值 Callable<Boolean> callable = new Callable<Boolean>() { public Boolean call() throws Exception { return true; // do something useful here } }; //定義retryer,指定輪詢條件,及結束條件 Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder() .retryIfResult(Predicates.<Boolean>isNull()) .retryIfExceptionOfType(IOException.class) .retryIfRuntimeException() .withStopStrategy(StopStrategies.stopAfterAttempt(3)) .build(); try { retryer.call(callable); } catch (RetryException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
retryer的條件是,callable的返回值是null或者有io異常或者運行時異常,則進行重試,重試次數爲3次;maven
2.若是想以每隔一段時間的頻率重試可參考以下代碼函數
Retryer<TaskResult> getExecutionStatusRetryer = RetryerBuilder.<TaskResult>newBuilder() .withWaitStrategy(WaitStrategies.fixedWait(5, TimeUnit.SECONDS)) .retryIfResult(r -> !Constants.completeStatus.contains(r.getStatus())) .withStopStrategy(StopStrategies.neverStop()) .build();
WaitStrategies定義等待策略:示例是5秒一次就會輪詢一次call的實現()
StopStrategies是定義中止輪詢策略的,StopStrategies.neverStop() 若知足輪詢條件的話,會一直進行重試下去
3.建立一個永久重試的重試器,在每次重試失敗後以遞增的指數退避間隔等待,直到最多5分鐘。 5分鐘後,每隔5分鐘重試一次。性能
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder() .retryIfExceptionOfType(IOException.class) .retryIfRuntimeException() .withWaitStrategy(WaitStrategies.exponentialWait(100, 5, TimeUnit.MINUTES)) .withStopStrategy(StopStrategies.neverStop()) .build();
若第一次重試是100毫秒後重試,若進行第二次則是增長到200毫秒進行重試,依次類推,知道達到5分鐘的上限,以後按照5分鐘一次的頻率進行重試ui
有興趣的可參考 指數回退:https://en.wikipedia.org/wiki/Exponential_backoffgoogle
4.建立一個永久重試的重試器,在每次重試失敗後以遞增的退避間隔等待,直到最多2分鐘。 2分鐘後,每隔2分鐘重試一次spa
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder() .retryIfExceptionOfType(IOException.class) .retryIfRuntimeException() .withWaitStrategy(WaitStrategies.fibonacciWait(100, 2, TimeUnit.MINUTES)) .withStopStrategy(StopStrategies.neverStop()) .build();
與指數等待策略相似,FibonacciWaitStrategy遵循的模式是每次嘗試失敗後等待時間增長。
FibonacciWaitStrategy是用斐波那契數列來計算等待時間,而不是指數函數。根據目前實踐中發現,fibonacciwaitstrategy可能比指數waitstrategy有更好的性能和更好的吞吐量-至少根據不一樣回退算法在不一樣重播機率下的性能比較。