百度上各种找,始终找不到,故只能自己写了
实现思想
java 的 LinkedBlockingQueue队列,会存在一个问题,即队列的入队和出队是互斥的,即某一刻有且仅有一个操作!
但是从逻辑上来说,出队和入队,不存在互斥的关系,那么是否可以不用实现相互不互斥呢?
基于这个想法,我们想到了双队列
即,一个队列专门入队,一个队列专门出队,当出对队列为空时,将两个队列切换,这样的话,就在一定程度上实现了,出对和入队不互斥。
代码
public class DoubleBlockingQueue<T> {
private volatile boolean direction = true;
private List<T> queue1 = new LinkedList<>();
private List<T> queue2 = new LinkedList<>();
private Object readLock = new Object();
private Object writeLock = new Object();
public void add(T o) {
synchronized (readLock) {
if (direction) {
queue1.add(o);
} else {
queue2.add(o);
}
}
}
public T poll() {
synchronized (writeLock) {
if (direction) {
return unqueue(queue2, queue1);
}
return unqueue(queue1, queue2);
}
}
private T unqueue(List<T> poll, List<T> put) {
if (poll.isEmpty()) {
synchronized (readLock) {
if (put.isEmpty())
return null;
direction = !direction;
}
return put.remove(0);
} else {
return poll.remove(0);
}
}
}
测试效果
** 近提升了一倍的效率! **
public static void main(String[] args) throws InterruptedException {
final int count = 10000 * 1000;
test1(count);// 975
test2(count);//1756
}
public static void test1(int count) throws InterruptedException {
DoubleBlockingQueue<Integer> queue1 = new DoubleBlockingQueue<>();
long l = System.currentTimeMillis();
Thread thread = new Thread(() -> {
int i = 0;
while (i < count) {
queue1.add(i++);
}
});
thread.start();
Thread thread1 = new Thread(() -> {
while (true){
Integer poll = queue1.poll();
if(poll!=null && poll== count -1)
return ;
}
});
thread1.start();
thread.join();
thread1.join();
System.out.println(System.currentTimeMillis() - l);
}
public static void test2(int count) throws InterruptedException {
LinkedBlockingQueue<Integer> queue1 = new LinkedBlockingQueue();
long l = System.currentTimeMillis();
Thread thread = new Thread(() -> {
int i = 0;
while (i < count) {
queue1.add(i++);
}
});
thread.start();
Thread thread1 = new Thread(() -> {
while (true){
Integer poll = queue1.poll();
if(poll!=null && poll== count -1)
return ;
}
});
thread1.start();
thread.join();
thread1.join();
System.out.println(System.currentTimeMillis() - l);
}