自分のスレッド(つまり、スレッドプールではない)を作成し、sleep
または他の割り込み可能なメソッドを呼び出す場合、コード内で他に誰も知らない場合、InterruptedExceptionを無視してもかまいませんスレッドで割り込みを行っています。
言い換えると、JVMがスレッドに割り込みできない限り、スレッドが存続することになっている場合、InterruptedExceptionはnever呼び出されるため、例外を飲み込むことができますか?
チェックされた例外を無視しても安全とは見なされません。
現時点では大丈夫かもしれませんが、別のプログラマーがコードを拡張する場合、標準的な動作、つまり割り込み呼び出しに反応するスレッドを期待します。
また、この場合、空のcatchブロックは危険です。これは、JVMが割り込みフラグを削除し、間違いなく再設定する必要があるためです。
Thread.currentThread().interrupt();
catchブロック内。私の意見では、これはInterruptedException
sの最小キャッチ実装です。ループ内のisInterrupted
フラグをチェックしても、それほど害はありません。
プロジェクトが少し成長したため、予期しないスレッドの動作を1〜2日検索するプログラマー自身の面倒に比べると、オーバーヘッドはほとんどありません。
コードの可読性がこれらのcatchの実装に苦しんでいると感じた場合は、独自のsafeSleep
ユーティリティメソッドを実装して、Exception
sを処理し、フラグを適切に設定できます。
一方、ハードウェア障害の場合、InterruptedException
はJVM自体によってスローされません。これはユーザーがException
のみを指定したものです。 したがって、 それだけです技術的に。 しかし、人的要因とプログラムの進化を過小評価すべきではありません。Thread
s参照を伝播しない場合、その上でThread.interrupt()
を呼び出すことができる他のThread
sはありません。
編集:ruakhが指摘したように、実際にはThread
s参照を取得する方法があります。 Thread.interrupt()
呼び出しをスケジュールします。そうすれば、熱中の開発者は、中断できないThread
を実装するクラスを見る必要さえないかもしれません。私の意見では、適切な例外処理を実装することは別の理由です。
別のこと:Exception
をスローしない場合は、INFO
を超えるレベルでそのようなイベントをログに記録することをお勧めします。
それを飲み込む代わりに、それが絶対に起こらないと確信しているなら、それを無視する代わりにクラッシュすることができます。たとえば、Error
(またはRuntimeException
)をスローします。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new Error(e);
}
エラーのJavadoc から:
エラーはThrowableのサブクラスであり、合理的なアプリケーションがキャッチしようとしてはならない重大な問題を示します。このようなエラーのほとんどは異常な状態です。
何かが決して起こらないと仮定する価値があると思うなら、もしそれが起こるなら、それは「異常な状態」であり、知っている人はただ「深刻な問題」かもしれない。
これを見るもう1つの方法は、将来誰かがdoesメソッドを中断した場合に、あたかも実行を継続することを望んでいる可能性があるということです。何も起こらなかった?いいえと思います。
例外が発生してはならないと思われる場合は、例外を決して飲み込むべきではありません。決して発生しないが発生してはならない条件を処理するコードを追加しないことを決定しても構いませんサイレント。
最低限行うべきことは:
catch(InterruptedException ex) {
throw new AssertionError(ex);
}
これにより、これが絶対に発生しないという主張が間違っている場合は必ず、それに気付くようになります。このパターンは、他の予期しない例外にも適用されます。 IOException
は、ターゲットOutputStream
がByteArrayOutputStream
であるか、Appendable
のFormatter
がStringBuilder
など.
ところで、Thread.sleep
に代わるものがあり、InterruptedException
をまったく処理する必要はありません。
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(timeInMillis));
このメソッドは、スレッドが中断されたときに以前に戻り、Thread
の中断状態を保持するため、コードが他の誰かによって使用されている場合に適切な処理を既に提供しますdoes割り込みを使用します(コードの呼び出し元が割り込み状態をチェックすると仮定します)。
私はまだこれらの問題に関する聖書を検討している本、Goetz et al。 実践におけるJavaの同時実行性は、第7章で以下の重要な部分を述べています(かなり同じ内容がGoetzの developerWorksの記事 にあります、これは無料であるという利点がありますが、本はいくつかの点でもう少し明確です。)
中断は協調的なメカニズムです。あるスレッドは、別のスレッドにそれがしていることを止めさせ、他の何かをさせることはできません。スレッドAがスレッドBを中断するとき、Aは、Bが便利な停止ポイントに到達したときに、Bが実行していることを停止するように単に要求しているだけです。
[...]
スレッドの割り込みポリシーを実装するコードのみが割り込み要求を飲み込む可能性があります。汎用タスクおよびライブラリコードは、割り込み要求を決して飲み込まないでください。
ですから、はい、あなたが概説した状況下でInterruptedException
を「飲み込む」ことができます。
本の重要なポイント:
各スレッドには独自の割り込みポリシーがあるため、割り込みの意味がわからない限り、スレッドを中断しないでください。
したがって、RuntimeException
、AssertionError
を使用した「クラッシュ」などの独自のポリシーを選択し、警告としてログに記録するか、この問題を他の人に文書化する限り、中断を完全に無視できます。知るために。最適なものは、スレッドが実際に何をしているかに依存し、その詳細はまだ提供していません。たとえば、ロケットで実行している場合(姿勢制御を行うなど)、JVM /ロケットをクラッシュさせたくないのは、仲間のプログラマー(あなたと同じ会社で働いていないかもしれないからです)彼はあなたが呼ぶライブラリを書きました]彼のコードのどこかで特定の契約を忘れて、あなたに安全に無視できる例外をダンプします: "発生した例外はランダムな失敗ではなく、設計エラーです。"
Projektが大きくなり、より複雑になった場合、誰も割り込みメソッドを呼び出さないと断言するのは難しくなっています。誰かがいつかこのメソッドを呼び出し、InterruptedExceptionが発生した場合、少なくともどこかにログを記録しないと、デバッグが非常に難しくなります。
無視すべきではありません。呼び出し元にスローバックするか、例外がスローされるとクリアされるスレッドの割り込みステータスを再アサートする必要があります。
catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
キャッチ後に速やかにスレッドを終了しない限り。
ここ はInterruptedException
sの取り扱いに関する記事です。
私は、InterruptedExceptionを無視することは安全かどうか、そのスレッドで何をしているかに依存すると思います。スレッドへの不要な割り込みがシステムまたはリソースを不要な状態(ダーティ、ロック、解放されていないためリソースのリークを引き起こす可能性がある)のままにする可能性があるシナリオがある場合、InterruptedExceptionを処理する責任は無視するべきではありません。スレッドを割り込み可能にするかどうかは、あなた次第です。
つまり、割り込みメカニズムは、主にキャンセルポリシーとタスクのクリーンアップの実装に使用されます。 IntrruptedExceptionを無視することは、政治的に正しいとは思えないかもしれませんが、タスクでクリーンアップするものがないか、特定のタスクキャンセルポリシーを持っていませんか?.