while循环在java BlockingQueue实现中

mor*_*fys 0 java blockingqueue

我最近看到了以下针对BlockingQueue的入队实现(源代码)

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);
}
Run Code Online (Sandbox Code Playgroud)

为什么while循环是必要的,可以while替换为if (this.queue.size() == this.limit)

似乎方法enqueue是同步的,因此一次只有1个线程可以在方法体中执行并进行调用wait().一旦线程被通知,它不能继续向前而不再检查this.queue.size() == this.limit条件?

mit*_*ull 5

Object.wait()最好的文档解释了它:

线程也可以在没有被通知,中断或超时的情况下唤醒,即所谓的虚假唤醒.虽然这在实践中很少发生,但应用程序必须通过测试应该导致线程被唤醒的条件来防范它,并且如果条件不满足则继续等待.换句话说,等待应该总是出现在循环中,如下所示:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait(timeout);
     ... // Perform action appropriate to condition
 }
Run Code Online (Sandbox Code Playgroud)