9
synchronized (Foo.class) {
    while (someCondition) {
        try {
            Foo.class.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();            
        }
    }
}

このスレッドは、他のスレッドが呼び出されたとき、interrupt()またはnotify()このスレッドで起動したようです。両者に違いはありますか?

- 編集 -

1つはオブジェクトに通知するためのもので、もう1つはスレッドを中断するためのものです。しかし、これらはどちらも同じ結果につながります。つまり、このスレッドが目覚めます。したがって、私が聞きたいのは、これら 2 つの状況の結果が互いにどのように異なるかです。

4

3 に答える 3

4

スレッドがいくつかのモニターで通知を呼び出すと、そのモニターで待機している単一のスレッドが起動されますが、どのスレッドが起動されるかはスケジューラによって決定されます。(別の方法として、スレッドは notifyAll を呼び出して、そのモニターを待機しているすべてのスレッドを起動し、すべてのスレッドがモニターをめぐって競合し、敗者は待機に戻ります。) そのため、呼び出しのターゲットが異なり、通知が行われます。これは、スケジューラーにウェイクアップするスレッドを選択するように指示します。

通知とは異なり、割り込みは特定のスレッドを対象とします。また、中断は、中断されたスレッドがモニターで待機している必要はありません。スレッドがモニターで待機を呼び出すには、最初にそのモニターを取得する必要があります。次に、スレッドの待機が完了するか中断されるまで、待機してそのモニターを解放します。

オラクル社の推奨事項は、中断はキャンセルのみに使用することです。また、java.util.concurrent のクラスは、キャンセルに割り込みを使用するように設計されています。

あなたの例では、制御がwhileループを離れないため、割り込みはあまり効果的ではありません。スレッドは待機している状態をチェックする必要があり、whileループ状態で割り込みフラグが設定されているかどうかをチェックしません。中断されたスレッドはすぐに待機状態に戻る可能性があります。

このコードが中断されたら待機状態に戻るのではなく終了させるには、中断されたフラグのステータスのチェックをループ条件に追加し、catch ブロックに割り込みフラグを設定させます (例外がスローされるとリセットされます)。

synchronized (Foo.class) {
    while (someCondition && !Thread.currentThread().isInterrupted()) {
        try {
            Foo.class.wait();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();            
        }
    }
}
于 2015-05-27T12:53:24.583 に答える