3

ループ内で 2 つのことを行うスレッドがあります。BlockingQueue からのオブジェクトを待ってから処理します。処理ロジックには、JVM の外部で観察可能な効果があり、アトミックに実行する必要があります。

現在、このスレッドは、https://stackoverflow.com/a/10961760/499922で説明されているように、揮発性ブール変数によって制御されています。ただし、これは、消費するメッセージがキューにそれ以上ない場合、スレッドが停止しないことを意味します。「Thread.interrupt()」はアトミック操作を途中で中断する可能性があるため、これを解決するために使用することはできません。

キューのメソッドを中断するtake()方法はありますが、他の操作はできませんか?

4

4 に答える 4

2

'Thread.interrupt()`は、アトミック操作を途中で中断する可能性があるため、これを解決するために使用することはできません。

これは行いません。揮発性フィールドの設定とほとんど同じフラグを設定するだけです。

非推奨であり、コードの任意の行をトリガーしてエラーをスローする可能性があるを使用した場合でも、Thread.stop()そのようなエラーをキャッチして、データが一貫した状態にあることを確認できます。

このキューからタスクを実行するためのキューとスレッドを作成する代わりに、これらの両方を備えたExecutorServiceを使用します。これを使用して、個々のタスクをキャンセル/中断し、複数のスレッドをサポートし、正常にまたはすぐにシャットダウンして、終了を待つことができます。

このホイールを再発明しないほうがよい可能性が非常に高いです。;)

于 2013-01-03T19:41:17.470 に答える
1

このような場合の最善の方法は、「ポイズン ピル」を使用することです。特定のアクションを切り替えるためだけに存在するオブジェクトをキューに配置します。

実際の Java 並行性 (155 ページ、私のコピーの 7.2.3) で広くカバーされています。そのセクションのプログラム例については、こちらを参照してください。

于 2013-01-03T19:33:24.547 に答える
0

volatile ブール値に依存する代わりに、スレッドの中断フラグに依存します。

while (!Thread.currentThread().isInterrupted()) {
    try {
        Object value = queue.take();
        handle(value);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

このようにして、フローがブロックさtake()れると、スレッドが中断されたときにすぐにループを終了します。それ以外のときに中断された場合は、現在のサイクルが完了した後にループを終了します。

または、オブジェクトがキューですぐに使用可能である限り、中断後もループを継続するようにコーディングできますpoll()

于 2013-01-03T19:33:25.233 に答える