では、実務でよくある 「リトライ処理」を安全に書くベストプラクティス を整理して解説します。
目的は「安全に何度か再試行しつつ、無限ループや例外落ちを防ぐこと」です。
1️⃣ 基本ルール
- 最大試行回数を必ず設ける
- 無限ループにならないようにする。
- 例:最大3回、5回など。
- 例外を捕まえて処理する
- ネットワーク、DB、ファイルなどは失敗する可能性がある。
try/catchで例外を捕まえ、ログや再試行に活かす。
- ログを出す
- 何回目のリトライか、例外内容をログに残す。
- デバッグや障害対応が簡単になる。
- ウェイト(待機時間)を入れる
- サーバーやAPIに負荷をかけすぎないように短時間待機。
- 実務では指数バックオフ(Exponential Backoff)が推奨される。
- 成功・失敗判定を明確にする
- 成功したら即終了、失敗したら再試行するロジックをシンプルに書く。
2️⃣ 実務向けのリトライ処理例(Java)
import java.io.IOException;
import java.util.Random;
public class SafeRetryExample {
public static void main(String[] args) {
final int MAX_RETRIES = 5; // 最大試行回数
int attempt = 0;
boolean success = false;
while (attempt < MAX_RETRIES && !success) {
attempt++;
try {
System.out.println("試行 " + attempt + " 回目: API呼び出し中...");
callApi(); // 実際の処理(例: ネットワーク通信)
success = true; // 成功した場合
System.out.println("API呼び出し成功!");
} catch (IOException e) {
System.err.println("失敗: " + e.getMessage());
if (attempt < MAX_RETRIES) {
try {
// 待機してから再試行(指数バックオフも可)
Thread.sleep(attempt * 1000L); // 1秒、2秒、3秒...と増やす
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("待機中に割り込み発生");
break;
}
} else {
System.err.println("上限に達したため処理を中止します");
}
}
}
}
// 疑似API呼び出し(ランダムに例外を発生)
private static void callApi() throws IOException {
if (new Random().nextBoolean()) {
throw new IOException("API通信エラー");
}
}
}
Java3️⃣ ポイント解説
while (attempt < MAX_RETRIES && !success)- 成功するか上限に達するまでループ。
- 無限ループにならない安全設計。
try/catchで例外を捕まえる- ネットワーク・DB・ファイル操作など、外部依存処理は必ず例外処理。
Thread.sleepで待機- サーバー負荷を避ける。
attempt * 1000Lで「1秒、2秒、3秒…」と徐々に増やす簡単な指数バックオフ。
- ログ出力
- 成功・失敗・試行回数を出すことで運用・デバッグが容易。
- 割り込み・中断対応
InterruptedExceptionを無視せず、Thread.currentThread().interrupt()で割り込み状態を維持。
4️⃣ さらに安全にするポイント
- 結果を返す関数にまとめる
- 複数箇所で再利用しやすい。
- 上限試行回数 + タイムアウト制御
- ネットワークがずっと応答しない場合でも無限に待たない。
- 例外をラップして呼び出し元に伝える
- ただログに出すだけで終わらず、必要なら再度 throw する。
💡 実務でよくあるシナリオ
- 外部API呼び出し → ネットワーク断 → 3回まで再試行
- DB接続 → 一時的にロック → 2秒ごとに再試行
- ファイル読み込み → 読み込み失敗 → 5回まで再試行して最後に警告
