この記事では、Java で再試行ロジックを実装する方法について説明します。
1. シンプルな for ループと try-catch
Java で再試行ロジックを実装する簡単な解決策は、指定された回数 (最大再試行値) を実行する for ループにコードを記述することです。
次のプログラムはこれを示しています。コードは try-catch でラップされていることに注意してください。try ブロック内で例外が発生した場合、制御は catch ブロックに移ります。例外を処理した後、システムは 1 秒後にコードを再度実行します。すべての再試行が使い果たされ、最後の再試行が失敗した後、例外がスローされます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
Javaをインポートします。ユーティリティ。ランダム;
パブリック クラス メイン {
プライベート 静的 最終 int MAX_RETRIES = 5 ;
public static void main ( String [ ] args ) throws InterruptedException {
for ( int i = 0 ; i <= MAX_RETRIES ; i ++ ) {
{ を試してください
// 等しい確率で 0 または 1 を生成する
int zeroOrOne = new Random ( ) . nextInt ( 2 ) ;
システム。アウト。println ( "乱数は.." + zeroOrOne ) ;
// 50% の確率で java.lang.ArithmeticException: / ゼロ
int 行 = 1 / zeroOrOne ;
// 成功しても再試行しない
休憩;
} catch (例外例) {
// 例外処理
システム。アウト。println ( ex.getMessage ( ) ) ; _ _ // 例外をログに記録します
// 再試行する前に 1 秒間スリープします (オプション)
スレッド。スリープ( 1000 ) ;
// 最後の再試行が失敗した場合は例外をスローします
if ( i == MAX_RETRIES ) {
exをスローします。
}
}
}
}
}
|
出力 (変化します):
乱数は .. 0 / ゼロを掛けた乱数は .. 0
/ ゼロを掛けた
乱数は .. 1
2. ユーザーインターフェース
インターフェイスを使用して、上記のロジックを簡単に調整して、タスク ロジックを再試行ロジックから分離できます。次のコードはこれを示しています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
Javaをインポートします。ユーティリティ。ランダム;
インターフェイス タスク {
ボイドラン (); _
void handleException (例外例) ;
}
パブリック クラス メイン {
プライベート 静的 最終 int MAX_RETRIES = 5 ;
public static void withMaxRetries ( Task task ) {
for (int i = 0; i <= MAX_RETRIES; i++) {
try {
task.run();
break; // don't retry on success
} catch (Exception ex) {
task.handleException(ex);
// throw exception if the last re-try fails
if (i == MAX_RETRIES) {
throw ex;
}
}
}
}
public static void main(String[] args) {
withMaxRetries(new Task() {
@Override
public void run() {
// generate 0 or 1 with equal probability
int zeroOrOne = new Random().nextInt(2);
System.out.println("Random number is.. " + zeroOrOne);
// 50% probability of getting java.lang.ArithmeticException: / by zero
int rand = 1 / zeroOrOne;
}
@Override
public void handleException(Exception ex) {
System.out.println(ex.getMessage()); // log the exception
try {
// sleep for 1 seconds before retrying (Optional)
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(e.getMessage()); // log the exception
}
}
});
}
}
|
输出(会有所不同):
随机数是.. 0 / 乘以零 随机数为.. 0 / 乘以零 随机数为.. 0
/ 乘以零
随机数为.. 1
3. 第三方库
如果您的项目准备使用第三方库,我们建议您使用以下库,这些库在 Java 中对重试逻辑有很强的支持。
1. 故障安全
故障保护是一个轻量级的零依赖库,用于处理 Java 8+ 中的故障。故障保护的工作原理是将可执行逻辑与一个或多个弹性策略包装在一起,这些策略可以根据需要组合和组合。
首先,创建一个重试策略,该策略定义应处理哪些故障以及何时应执行重试:
1
2
3
4
5
|
RetryPolicy<Object> retryPolicy = RetryPolicy.builder()
.handle(ConnectException.class)
.withDelay(Duration.ofSeconds(1))
.withMaxRetries(3)
.build();
|
然后,您可以重试执行 或:Runnable
Supplier
1
2
3
4
5
|
// Run with retries
Failsafe.with(retryPolicy).run(() -> connect());
// Get with retries
Connection connection = Failsafe.with(retryPolicy).get(() -> connect());
|
阅读更多 – 故障安全文档
2. 番石榴重试
guava 重试模块提供了一种通用方法,用于重试任意 Java 代码,具有特定的停止、重试和异常处理功能,这些功能通过 Guava 的谓词匹配得到增强。
某些功能的最小示例如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
Callable<Boolean> callable = new Callable<Boolean>() {
public Boolean call() throws Exception {
return true; // do something useful here
}
};
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
.retryIfResult(Predicates.<Boolean>isNull())
.retryIfExceptionOfType(IOException.class)
.retryIfRuntimeException()
. withStopStrategy ( StopStrategies .stopAfterAttempt ( 3 ) ) _
. ビルド( ) ;
{ を試してください
リトライヤ。コール(呼び出し可能);
} キャッチ ( RetryException e ) {
e . printStackTrace ( ) ;
} キャッチ ( ExecutionException e ) {
e . printStackTrace ( ) ;
}
|
これは、結果が null であるか、発生するか、メソッドからその他の結果がスローされるたびに再試行されます。再試行を 3 回試行すると停止し、最後に失敗した試行に関する情報をスローします。メソッドから他のものがポップされると、ラップされて再スローされます。Callable
IOException
RuntimeException
call()
RetryException
Exception
call()
ExecutionException
続きを読む – Guava Retry ドキュメント
Java で再試行ロジックを実装する方法についてお伝えできることは、これですべてです。