24

どちらもプログラムの実行を停止します。ただし、これがどのように行われるかにはいくつかの違いがあるはずです。彼らは何ですか?

4

3 に答える 3

43

概要

  1. thread.interrupt()スレッドを停止しません。マルチスレッドプログラムでの調整に使用されます。自分が何をしているのかを正確に理解していない限り、使用しないでください。
  2. 意志を投げるRuntimeExceptionと(通常)スレッドは終了しますが、必ずしもプログラムは終了しません。
  3. System.exit(int) ほとんどの場合、プログラムを終了し、ステータスコードを返します。
  4. 異常な状況でSystem.exit(int)は、実際にはプログラムを停止しない場合があります。Runtime.getRuntime().halt(int)一方、常にそうです。

スレッドの中断

あなたの最初の文が間違っているのではないかと思います。Thread.currentThread().interrupt()スレッドまたはプログラムを停止しません。

スレッドを中断することは、スレッドを停止する必要があることを通知する方法ですが、これは協力的な取り組みです。スレッド内のコードは、中断されたステータスを時々チェックすることになっています(ほとんどの場合、これもオプションです)。が中断された場合は停止します。そうしないと何も起こりません。

具体的には、スレッド(任意のスレッド、現在実行中のスレッドを含む)に割り込みをかけると、割り込みフラグのみが設定されます。標準ライブラリの特定のメソッドはInterruptedExceptionをスローしますが、これはスレッドが中断されたことを通知する方法でもあります。このような状況で何をすべきかは、そのスレッドで実行されているコード次第です。

BrianGoetzによるJavaConcurrencyinPracticeの本の関連部分は次のとおりです。

スレッドは、スレッドを中断し、スレッドが中断されたかどうかを照会するための割り込みメソッドを提供します。各スレッドには、中断されたステータスを表すブールプロパティがあります。スレッドを中断すると、このステータスが設定されます。

中断は協調的なメカニズムです。あるスレッドが別のスレッドに、実行中の処理を停止して他のことを強制することはできません。スレッドAがスレッドBに割り込んだ場合、Aは、都合のよい停止ポイントに到達したときに、Bが実行していることを停止するように要求しているだけですが、APIまたは言語仕様には、特定のアプリケーションレベルのセマンティクスを要求するものはありません。割り込み、割り込みの最も賢明な使用法は、アクティビティをキャンセルすることです。中断に対応するブロック方法により、長時間実行されているアクティビティをタイムリーにキャンセルすることが容易になります。

例外とSystem.exit(int)

JavadocはSystem.exit(int)言う:

現在実行中のJava仮想マシンを終了します。引数はステータスコードとして機能します。慣例により、ゼロ以外のステータスコードは異常終了を示します。

したがって、電話exit()をかけると(ほぼ)間違いなくプログラムが停止します。RuntimeException(または)をスローするのとは対照的にError、これはコールスタックのどこかでキャッチできず、他のスレッドが実行されているかどうかにも依存しません。一方、キャッチされなかった例外は、スローされたスレッドを終了しますが、他の(デーモン以外の)スレッドがある場合、プログラムは実行を継続します。

例外をスローすることとのもう1つの違いはexit()、(キャッチされない例外のように)コンソールに何も出力せず、代わりにプログラムに特定のステータスコードを返すことです。ステータスコードはシェルスクリプトやバッチスクリプトで使用されることがありますが、それ以外はあまり役に立ちません。

Runtime.halt(int)

最後に(完全を期すために)、Javaプログラムを終了する3番目の可能性を指摘したいと思います。がSystem.exit(int)呼び出されると(またはプログラムが他の方法で終了すると)、ランタイムはJava仮想マシンが停止する前にクリーンアップ作業を実行します。これは、 Runtime.exit(int)のJavadoc ( System.exit(int):によって呼び出されます)で説明されています。

仮想マシンのシャットダウンシーケンスは、2つのフェーズで構成されています。最初のフェーズでは、登録されているすべてのシャットダウンフックが存在する場合、不特定の順序で開始され、終了するまで同時に実行できます。第2フェーズでは、終了時のファイナライズが有効になっている場合、呼び出されていないすべてのファイナライザーが実行されます。これが完了すると、仮想マシンは停止します。

デッドロックなどが原因でシャットダウンフックまたはファイナライザーの完了が妨げられた場合、プログラムが実際に終了することはありません。JVMが停止することを保証する唯一のメソッドはRuntime.halt(int)です:

この方法は、細心の注意を払って使用する必要があります。exitメソッドとは異なり、このメソッドではシャットダウンフックが開始されず、finalization-on-exitが有効になっている場合は呼び出されないファイナライザーが実行されません。

于 2012-09-24T20:35:36.683 に答える
20

他の(デーモン以外の)スレッドが実行されている場合、メインスレッドを停止してもJVMは終了しません。System.exit()は、他のすべてのスレッドを強制終了します。

于 2012-09-24T20:32:54.410 に答える
1

マルチスレッドアプリケーションでは、を実行しているスレッドが複数あります。Thread.currentThread().interrupt()現在実行中のスレッドに割り込むだけですが、メインスレッドに割り込まれたとしても、残りのスレッドは実行されます。

一方、System.exit(0)結果としてシステムは終了します。そして、すべてのスレッドが強制終了されます。

于 2012-09-24T20:35:10.293 に答える