そうでない場合、誰がJavaスレッドのinterrupt()メソッドを呼び出していますか?


87

Java Concurrency in Practiceを読んだり、読み直したり、このテーマに関するいくつかのスレッドを読んだり、IBMの記事「InterruptedExceptionに対処する」を読んだりしましたが、理解できないことがあり、壊れている可能性があります。 2つの質問に分けてください:

  1. 自分で他のスレッドを中断したことがない場合、InterruptedExceptionをトリガーできるのは何ですか?

  2. 自分でinterrupt()を使用して他のスレッドを中断したことがない場合(たとえば、ポイズンピルやwhile(!cancelled)スタイルループ[両方ともJCIPで説明されている]など、作業中のスレッドをキャンセルするために他の手段を使用しているため)、それでは、InterruptedExceptionはどういう意味ですか?捕まえたらどうすればいいの?アプリをシャットダウンしますか?

回答:


50

スレッド割り込みメカニズムは、(協調する)スレッドに、実行中の停止要求に応答させるための推奨される方法です。すべてのスレッド(私が思うスレッド自体を含む)はinterrupt()、スレッドを呼び出すことができます。

実際には、の通常のユースケースにinterrupt()は、ある種のフレームワークまたはマネージャーがワーカースレッドに実行を停止するように指示することが含まれます。ワーカースレッドが「割り込み認識」である場合、例外を介して、または割り込みフラグを定期的にチェックすることにより、割り込みされたことを認識します。それが中断されたことに気付くと、行儀の良いスレッドはそれが行っていることを放棄し、それ自体を終了します。

上記のユースケースを想定すると、Javaフレームワーク内で実行された場合、または何らかのワーカースレッドから実行された場合、コードが中断される可能性があります。そして、それが中断されたとき、あなたのコードはそれがしていることを放棄し、最も適切な手段によってそれ自身を終わらせるべきです。コードの呼び出し方法によっては、これを返すか、適切な例外をスローすることで実行できます。しかし、それはおそらく呼び出すべきではありませんSystem.exit()。(アプリケーションは、なぜ中断されたのかを必ずしも知っているわけではなく、フレームワークによって中断される必要のある他のスレッドがあるかどうかも確かに知りません。)

一方、コードが何らかのフレームワークの制御下で実行されるように設計されていない場合InterruptedExceptionは、これが予期しない例外であると主張する可能性があります。つまり、バグです。その場合、他のバグと同じように例外を処理する必要があります。たとえば、チェックされていない例外でラップし、他の予期しないチェックされていない例外を処理するのと同じ時点でキャッチしてログに記録します。(または、アプリケーションは単に割り込みを無視して、実行していたことを続行することもできます。)


1)自分で他のスレッドを中断したことがない場合、InterruptedExceptionをトリガーできるのは何ですか?

あなたの場合は、1つの例は、あるRunnableオブジェクトが使用して実行されているExecutorServiceshutdownNow()サービスに呼ばれています。そして理論的には、サードパーティのスレッドプールまたはスレッド管理フレームワークは合法的にこのようなことを行うことができます。

2)interrupt()を使用して自分で他のスレッドを中断したことがない場合...InterruptedExceptionそれではどういう意味ですか?捕まえたらどうすればいいの?アプリをシャットダウンしますか?

コードベースを分析して、何がinterrupt()呼び出しを行っているのか、そしてその理由を理解する必要があります。それを理解したら、アプリの>>あなたの<<部分が何をする必要があるかを理解することができます。

なぜInterruptedExceptionスローされているのかがわかるまでは、ハードエラーとして扱うことをお勧めします。たとえば、スタックトレースをログファイルに出力し、アプリをシャットダウンします。(明らかに、それは必ずしも正しい答えではありません...しかし、ポイントはこれが「バグ」であり、開発者/メンテナの注意を引く必要があるということです。)

3)誰が/何を呼んでいるのinterrupt()かを知るにはどうすればよいですか?

これに対する良い答えはありません。私が提案できる最善の方法は、にブレークポイントを設定Thread.interrupt()し、呼び出しスタックを確認することです。


12

コードを他のライブラリと統合することにした場合、他のライブラリがコードを呼び出すことができinterrupt()ます。たとえば、将来、ExecutorService内でコードを実行することにした場合、interrupt()。を介して強制的にシャットダウンする可能性があります。

簡単に言うと、コードが現在実行されている場所だけでなく、将来どのようなコンテキストで実行される可能性があるかについても検討します。例えば、あなたはそれを図書館に置くつもりですか?コンテナ ?他の人はそれをどのように使用しますか?再利用しますか?


shutdownNowだけがinterrupt()メソッドを呼び出すと思いました。シャットダウンにも当てはまりますか?
Harinder 2017年

9

他の人が指摘しているように、スレッドの中断(実際には、ブロッキング呼び出しの中断)は通常、クリーンに終了したり、進行中のアクティビティをキャンセルしたりする目的で使用されます。

ただし、InterruptedException単独で「終了コマンド」として扱うべきではありません。代わりに、割り込みは、スレッドの実行ステータスを制御する手段と同じように考える必要がありますObject.notify()。呼び出しからウェイクアップした後の現在の状態を確認するのと同じ方法でObject.wait()(ウェイクアップが待機条件が満たされていることを意味するとは限りません)、割り込みで微調整された後、割り込みが発生した理由を確認する必要があります。通常、これを行う方法があります。たとえばjava.util.concurrent.FutureTaskisCancelled()メソッドがあります。

コードサンプル:

public void run() {
    ....
    try {
        .... // Calls that may block.
    } catch (InterruptedException e) {
        if (!running) {  // Add preferred synchronization here.
            return; // Explicit flag says we should stop running.
        }
        // We were interrupted, but the flag says we're still running.
        // It would be wrong to always exit here. The interrupt 'nudge'
        // could mean something completely different. For example, it
        // could be that the thread was blocking on a read from a particular
        // file, and now we should read from a different file.
        // Interrupt != quit (not necessarily).
    }
    ....
}
public void stop() {
    running = false; // Add preferred synchronization here.
    myThread.interrupt();
}

3

質問の問題は「私」です。「私」は通常、クラスの単一のインスタンスを指します。つまり、低レベルのコード(クラス)の特定の部分は、システム全体の実装に依存するべきではないということです。あなたはいくつかの「アーキテクチャ上の」決定をしていると言っています(どのプラットフォームで実行するかなど)。

JREから発生する可能性のある予期しない割り込みは、java.util.concurrentアプレット内のタスクのキャンセルとアプレットのシャットダウンです。

スレッド割り込みの処理は通常、正しく記述されていません。したがって、可能な場合は割り込みを発生させないようにアーキテクチャを決定することをお勧めします。ただし、コード処理割り込みは常に正しく記述する必要があります。現在、プラットフォームから割り込みを取り除くことはできません。


こんにちはトム、私はcljpからあなたの名前を覚えています;)まあ、正確に:私は自分でinterrupt()をスローする必要はありませんでした... InterruptedExceptionをキャッチし、中断されたステータスを再アサートする必要がない限り、これはまだ100%ではありません私には明らかです。私はここで新しく、賛成票と回答/コメント(正しいものと間違ったものの両方)の数に驚いています:明らかにそれは些細なことではないか、少なくとも通常はよく説明されていない主題です。とは
いえ

3

これは、独自のスレッドクラス(extending)を作成し、スタックトレースをたとえばStringフィールドに記録してから、super.interrupt()に転送するメソッドjava.lang.Threadをオーバーライドすることで学習できますinterrupt()

public class MyThread extends Thread {

    public volatile String interruptStacktrace; // Temporary field for debugging purpose.

    @Override
    public void interrupt() {
        interruptStacktrace = dumpStack(); // You implement it somehow...

        super.interrupt();
    }
}

1

すでに述べたように、別のライブラリがスレッドを中断する可能性があります。ライブラリがコードからスレッドに明示的にアクセスできない場合でも、実行中のスレッドのリストを取得し、次のメソッドを使用してそのように中断することができます。


1

なぜあなたが中断について少し混乱しているのか理解できたと思います。私の答えを次のように考えてください。

自分で他のスレッドを中断したことがない場合、InterruptedExceptionをトリガーできるのは何ですか?

まず、他のスレッドに割り込むことができます。JCiPでは、所有していないスレッドを決して中断してはならないことが述べられていることを私は知っています。ただし、このステートメントを正しく理解する必要があります。つまり、任意のスレッドで実行されている可能性のあるコードは、スレッドの所有者ではないため、中断ポリシーの手がかりがないため、中断を処理するべきではありません。したがって、他のスレッドで割り込みを要求することはできますが、その所有者に割り込みアクションを実行させます。タスクコードではなく、中断ポリシーがカプセル化されています。少なくとも、中断フラグを設定するように注意してください。

それでも割り込みが発生する可能性がある理由はたくさんあります。タイムアウト、JVM割り込みなどがあります。

自分でinterrupt()を使用して他のスレッドを中断したことがない場合(たとえば、ポイズンピルやwhile(!cancelled)スタイルループ[両方ともJCIPで説明されている]など、作業中のスレッドをキャンセルするために他の手段を使用しているため)、それでは、InterruptedExceptionはどういう意味ですか?捕まえたらどうすればいいの?アプリをシャットダウンしますか?

ここでは非常に注意する必要があります。InterruptedException(IE)をスローしたスレッドを所有している場合は、それをキャッチしたときに何をすべきかを知っています。たとえば、アプリ/サービスをシャットダウンするか、この強制終了されたスレッドを新しいスレッドに置き換えることができます。ただし、スレッドを所有していない場合は、IEをキャッチすると、コールスタックの上位に再スローするか、何かを実行した後(ロギングの可能性があります)、割り込みステータスをリセットして、制御がスレッドに到達したときに、このスレッドを所有するコードがスレッドを所有できるようにします。スレッドが中断されたことを知り、中断ポリシーを知っているのはスレッドだけなので、そのままのアクションを実行します。

これがお役に立てば幸いです。


0

InterruptedExceptionルーチンがいることを言うかもしれ中断され、必ずしも必要ではないが、それはなること。

割り込みを予期しない場合は、他の予期しない例外と同じように扱う必要があります。予期しない例外が致命的な結果をもたらす可能性があるクリティカルセクションにある場合は、リソースをクリーンアップして正常にシャットダウンすることをお勧めします(割り込みに依存しない適切に設計されたアプリケーションが使用されていることを示す割り込みシグナルを取得するため)ある意味では設計されていないので、何か問題があるに違いありません)。または、問題のコードが重要ではない、または些細なものである場合は、割り込みを無視(またはログに記録)して続行することをお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.