在java生产者消费者专题---谈谈优化(二)中提到真正需要唤醒的是当队列满的时候唤醒消费者线程,当队列空的时候唤醒生产者线程,但在文章最后指出notifyAll不能换成notify因为还是可能出现死锁,实际上目前并没有真正达到按需唤醒的目的,现使用Condition条件队列进行优化,代码如下:
public class QueueWithCondition<T> extends BlockingQueue<T> {
private LinkedList<T> queue = new LinkedList<>();
private Lock lock = new ReentrantLock();
private Condition full = lock.newCondition();
private Condition empty = lock.newCondition();
private final int cacheSize;
public QueueWithCondition(int cacheSize) {
super();
this.cacheSize = cacheSize;
}
public T take() {
try{
lock.lock();
while(true) {
if(queue.size()>0) {
boolean full = queue.size() == cacheSize;
T obj = queue.poll();
if(full) {
this.full.signal();
}
return obj;
}else {
try {
empty.await();
} catch (InterruptedException e) {
}
}
}
}finally {
lock.unlock();
}
}
public void put(T obj) {
try{
lock.lock();
while (true) {
if (queue.size() < cacheSize) {
boolean empty=queue.size()==0;
queue.offer(obj);
if(empty) {
this.empty.signal();
}
break;
} else {
try {
full.await();
} catch (InterruptedException e) {
}
}
}
}finally {
lock.unlock();
}
}
}
改进后平均每秒消费消息72810个比原先每秒消费个数65541要快不少。
使用Condition条件队列可以对不同的等待条件进行分区,这是wait、notify做不到的。