我在这个question中看到了一段我无法理解的代码片段(很可能是由于这个领域的初学者)。这个问题谈到了“明显的竞争条件,有时生产者会完成,发出信号,消费者工作者会在消耗队列中的所有内容之前停止。”
根据我的理解,只有在生产者决定不在队列中添加任何项目之后,才会在消费者上设置“isRunning”。因此,如果消费者线程将isRunning视为FALSE然后看到inputQueue为空,那么将来不可能有更多的东西被添加到队列中。 显而易见,我错了,错过了一些东西,因为没有人回答这个问题说这个问题的情景是不可能的。那么,有人可以解释一下这种竞争条件会导致这种竞争条件吗?
事实上,我看到了别的问题。例如,如果多个消费者线程看到生产者正在运行,并且说队列有一个项目,那么许多线程可能会进入被阻止的'take'。如果制作人现在STOPS,而一个线程就会出现'take', 其他线程永远被阻止在'take'上。有趣的是,没有人回答这个问题也指出了这个问题。所以,我对此的理解也可能有问题?!
我不想在这个问题中添加这个作为评论,因为这是一个老问题,我怀疑可能永远得不到答案! 我在这里复制/放置该问题的代码以供快速参考。
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;
}
答案 0 :(得分:1)
我认为原始问题的OP可能意味着
while(isRunning && !inputQueue.isEmpty())
而不是
while(isRunning || !inputQueue.isEmpty())
前者明显产生原始海报(*)描述的问题,而后者确实存在您在第二点中描述的问题。这是一个简单的疏忽,但现在我们可以注意到这两种方法都是不正确的。
(*)并以某种方式假设队列永远不会为空。
答案 1 :(得分:0)
这两个问题都是正确的。是&&
是正确的,||
不是。至于第二个问题,答案是使用poison pill
或超时,两种方式都可以解决问题。
对于我,我会创建一个新的同步类,它聚合队列和isRunning
变量,以便更改isRunning
会导致take()
中的异常,从而表示工作结束。