条件队列让一组线程-称作等待集-以某种方式等待相关条件变成真,它也由此得名。不同于传统的队列,它们的元素是数据项;条件队列的元素是等待相关条件的线程。
@ThreadSafe
public classBoundedBuffer<V> extendsBaseBoundedBuffer<V>{
public BoundedBuffer(int size){super(size);}
public synchronized void put(V v)throws InterruptedException{
while (isFull())
wait();
doPut(V);
notifyAll();
}
public synchronized V take() throws InterruptedException{
while (isEmpty())
wait();
V v=doTake();
notifyAll();
return v;
}
}
当从wait中唤醒后,必须再次测试条件谓词。规范写法如下:
pulbic stateDependentMethod() throws InterruptedException{
//条件谓词必须被锁守护
synchronized(lock){
while (!conditionPredicate())
lock.wait();
//现在,对象处于期望的状态中
}
}
当使用条件等待时,
1)永远设置一个条件谓词-一些对象状态的测试,线程执行前必须满足它
2)永远在调用wait前测试条件谓词,并从wait中返回后再次测试
3)永远在循环中调用wait
4)确保构成条件谓词的状态变量被锁保护,而这个锁正是与条件队列相关联的
5)当调用wait、notify或notifyAll时,要持有与条件队列相关联的锁,并且在检查条件谓词之后,开始执行被保护的逻辑之前,不要释放锁
无论何时,当你在等待一个条件,一定要确保有人会在条件谓词变为真时通知你,一般使用nofifyAll。
只有同时满足下述条件后,才能用单一的notify取代notifyAll:
相同的等待者。只有一个条件谓词与条件队列相关,每个线程从wait返回后执行相同的逻辑;并且,一进一出,一个对条件变量的通知,至多激活一个线程执行。
向上述代码中的生产者-消息者,2个条件谓词(非空和非满)与条件队列相关,必须使用notifyAll