この質問で理解できないコードのスニペットを見ました(おそらく、この分野の初心者であるという事実が原因です)。質問は、「時々プロデューサーが終了し、それを通知し、ConsumerWorkers がキュー内のすべてを消費する前に停止する明らかな競合状態」について語っています。
私の理解では、「isRunning」は、プロデューサーがキューにアイテムを追加しないことを決定した後にのみ、コンシューマーに設定されます。そのため、コンシューマ スレッドが isRunning を FALSE として認識し、inputQueue が空であることを認識した場合、将来キューに追加される可能性はありません。明らかに、私は間違っていて何かが欠けています。その質問に答えた人は誰も質問のシナリオが不可能だと言ったからです。それで、誰かがこの競合状態を引き起こす一連のイベントを説明できますか?
実際、私は何か別の問題を見ています。たとえば、複数のコンシューマ スレッドがプロデューサが実行中であることを確認し、キューに 1 つのアイテムがあると言うと、多くのスレッドがブロックされた「テイク」に入る可能性があります。プロデューサーがここで停止すると、1 つのスレッドが「テイク」から出てきますが、他のスレッドは「テイク」で永久にブロックされます。興味深いことに、質問に答えた人は誰もこの問題を指摘しませんでした. だから、これについての私の理解もおそらく間違っていますか?!
これは古い質問であり、私の疑問は決して答えられない可能性があるため、その質問にコメントとして追加したくありませんでした! クイックリファレンスのために、その質問のコードをここにコピー/配置しています。
public class ConsumerWorker implements Runnable{
private BlockingQueue<Produced> inputQueue;
private volatile boolean isRunning = true;
public ConsumerWorker(BlockingQueue<Produced> inputQueue) {
this.inputQueue = inputQueue;
}
@Override
public void run() {
//worker loop keeps taking en element from the queue as long as the producer is still running or as
//long as the queue is not empty:
while(isRunning || !inputQueue.isEmpty()) {
System.out.println("Consumer "+Thread.currentThread().getName()+" START");
try {
Object queueElement = inputQueue.take();
//process queueElement
} catch (Exception e) {
e.printStackTrace();
}
}
}
//this is used to signal from the main thread that he producer has finished adding stuff to the queue
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}