在java生产者消费者专题---谈谈优化(一)中说明了当满足唤醒条件时需要使用notifyAll而不是notify,但是notifyAll依然存在效率上的问题,因为notifyAll唤醒的是所有线程,由于生产者线程会在队列满的时候进入等待、消费者线程会在队列为空的时候进入等待,因此生产者需要唤醒的条件就是队列满了、消费者需要唤醒的条件就是队列空了,不能像原来一样不加检测条件直接唤醒,于是程序优化如下:
package pro_con;
import java.util.LinkedList;
public class QueueWithWait2 extends BlockingQueue {
private LinkedList queue = new LinkedList<>();
private final int cacheSize;
public QueueWithWait2(int cacheSize) {
super();
this.cacheSize = cacheSize;
}
public T take() {
synchronized (queue) {
while(true) {
if(queue.size()>0) {
boolean full = queue.size() == cacheSize;
T obj = queue.poll();
if(full) {
queue.notifyAll();
}
return obj;
}else {
try {
queue.wait();
} catch (InterruptedException e) {
}
}
}
}
}
public void put(T obj) {
synchronized (queue) {
while (true) {
if (queue.size() < cacheSize) {
boolean empty=queue.size()==0;
queue.offer(obj);
if(empty) {
queue.notifyAll();
}
break;
} else {
try {
queue.wait();
} catch (InterruptedException e) {
}
}
}
}
}
}
改进后平均每秒消费消息65541个比原先每秒消费个数63523稍微快点。
注意这里的notifyAll还不能换成notify因为还会发生类似java生产者消费者专题---谈谈优化(一)中的死锁情况,其实这里也并没有真正达到按需唤醒的目标,会在下一篇进行分析。