我最近看到了以下 BlockingQueue 入队的实现 (source)
public synchronized void enqueue(Object item)
throws InterruptedException {
while(this.queue.size() == this.limit) {
wait();
}
if(this.queue.size() == 0) {
notifyAll();
}
this.queue.add(item);
}
为什么需要while
循环,while
可以用if (this.queue.size() == this.limit)代替
看来方法入队是同步的,因此一次只能有 1 个线程在方法体中执行并调用 wait()
。一旦线程收到通知,难道它不能继续前进而不再次检查 this.queue.size() == this.limit
条件吗?
最佳答案
关于Object.wait()
的文档解释得最好:
线程也可以在没有被通知、中断或超时的情况下唤醒,即所谓的虚假唤醒。虽然这种情况在实践中很少发生,但应用程序必须通过测试应导致线程被唤醒的条件来防止这种情况,并在条件不满足时继续等待。换句话说,等待应该总是在循环中发生,就像这样:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
关于java - java BlockingQueue 实现中的 while 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9839388/