我一直在玩我自己的版本,使用“if”,一切似乎都运行良好。当然,如果使用 signalAll() 而不是 signal(),这会严重崩溃,但是如果一次只通知一个线程,这怎么会出错呢?
他们的代码 here - 查看 put() 和 take() 方法;在 JavaDoc for Condition 的顶部可以看到一个更简单、更切题的实现。 .
下面是我实现的相关部分。
public Object get() {
lock.lock();
try {
if( items.size() < 1 )
hasItems.await();
Object poppedValue = items.getLast();
items.removeLast();
hasSpace.signal();
return poppedValue;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
} finally {
lock.unlock();
}
}
public void put(Object item) {
lock.lock();
try {
if( items.size() >= capacity )
hasSpace.await();
items.addFirst(item);
hasItems.signal();
return;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
附言我知道一般来说,尤其是在像这样的 lib 类中,应该让异常渗透。
最佳答案
防止虚假唤醒。 JVM 无法向您保证线程将再次开始运行的唯一可能原因是因为您以预期的方式调用了信号。有时它会不小心启动并运行(Spurious wake up)。所以如果你想要运行的条件实际上不是真的,你必须再次等待。
这在 wait 方法的 javadoc 中有解释: http://java.sun.com/javase/6/docs/api/java/lang/Object.html#wait%28long%29
并在文档中提到等待: http://java.sun.com/javase/6/docs/api/java/util/concurrent/locks/Condition.html#await%28%29
The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:
Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
Some other thread invokes the signalAll() method for this Condition; or
Some other thread interrupts the current thread, and interruption of thread suspension is supported; or
* A "spurious wakeup" occurs.
Condition 接口(interface)的某些实现可能会抑制虚假唤醒,但依赖于此将依赖于实现细节并使您的代码不可移植。
关于java - 为什么 java.util.concurrent.ArrayBlockingQueue 在调用 await() 时使用 'while' 循环而不是 'if'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2960581/