以下の処理方法の違いは何ですかInterruptedException
? 最も良い処理方法は何ですか?
try {
// ...
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
...または:
try {
//...
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
これら 2 つがどのようなシナリオで使用されるのかも知りたいです。
ベストアンサー1
InterruptedException を処理する次の方法の違いは何ですか? 最適な方法は何ですか?
おそらく、 をスローするメソッドを呼び出したために、この質問をするようになったのでしょうInterruptedException
。
まず、throws InterruptedException
それが何であるかを理解するべきです。それは、メソッド シグネチャの一部であり、呼び出しているメソッドを呼び出した結果として起こり得るものです。まずは、がInterruptedException
メソッド呼び出しの完全に有効な結果であるという事実を受け入れることから始めましょう。
さて、呼び出しているメソッドがそのような例外をスローした場合、メソッドは何をすべきでしょうか?次のことを考えれば答えがわかります。
実装しているメソッドが をスローするのは理にかなっていますかInterruptedException
?言い換えると、メソッドInterruptedException
を呼び出すときに が合理的な結果になるでしょうか?
はいの場合は、メソッド
throws InterruptedException
シグネチャの一部にして、例外を伝播させる必要があります (つまり、まったくキャッチしないでください)。例: メソッドは、計算を終了して結果を返すために、ネットワークからの値を待機します。ブロッキング ネットワーク呼び出しがをスローすると、
InterruptedException
メソッドは通常の方法で計算を終了できません。伝播させますInterruptedException
。int computeSum(Server server) throws InterruptedException { // Any InterruptedException thrown below is propagated int a = server.getValueA(); int b = server.getValueB(); return a + b; }
いいえの場合は、メソッドを で宣言せず
throws InterruptedException
、例外をキャッチする必要があります (キャッチする必要があります)。この状況では、次の 2 つの点に留意することが重要です。誰かがあなたのスレッドを中断しました。その人はおそらく、操作をキャンセルしたり、プログラムを正常に終了したり、その他のことをしたいと思っているでしょう。その人に対しては礼儀正しく対応し、これ以上何もせずにメソッドから戻る必要があります。
メソッドが割り込みが発生した場合に適切な戻り値を生成することができたとしても
InterruptedException
、スレッドが割り込まれたという事実は依然として重要です。特に、メソッドを呼び出すコードは、メソッドの実行中に割り込みが発生したかどうかに関心がある可能性があります。したがって、割り込みフラグを設定して、割り込みが発生したという事実をログに記録する必要があります。Thread.currentThread().interrupt()
例: ユーザーは 2 つの値の合計を印刷するように要求しました。
Failed to compute sum
合計を計算できない場合は、" " を印刷しても問題ありません ( が原因でスタック トレースでプログラムがクラッシュするよりはるかに優れていますInterruptedException
)。つまり、このメソッドを で宣言しても意味がありませんthrows InterruptedException
。void printSum(Server server) { try { int sum = computeSum(server); System.out.println("Sum: " + sum); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // set interrupt flag System.out.println("Failed to compute sum"); } }
ここまでで、ただ実行するのはthrow new RuntimeException(e)
悪い考えであることが明らかになったはずです。呼び出し元に対してあまり礼儀正しくありません。新しいランタイム例外を作成することもできますが、根本的な原因 (誰かがスレッドの実行を停止したい) が失われる可能性があります。
その他の例:
実装
Runnable
: ご存知のとおり、 のシグネチャではRunnable.run
の再スローは許可されていませんInterruptedExceptions
。を実装することに同意したということは、の可能性に対処することに同意したというRunnable
ことです。次のような別のインターフェースを選択するか、InterruptedExceptions
Callable
または、上記の 2 番目の方法に従ってください。
呼び出し
Thread.sleep
: ファイルの読み取りを試行しており、仕様では 1 秒間隔で 10 回試行する必要があるとされています。 を呼び出しますThread.sleep(1000)
。したがって、 に対処する必要がありますInterruptedException
。 などのメソッドの場合、「中断されると、ファイルの読み取りを試みるアクションを完了できません」tryToReadFile
と言うのは完全に理にかなっています。言い換えると、メソッドが をスローするのは完全に理にかなっています。InterruptedExceptions
String tryToReadFile(File f) throws InterruptedException { for (int i = 0; i < 10; i++) { if (f.exists()) return readFile(f); Thread.sleep(1000); } return null; }
この投稿は記事として書き直されましたここ。