JUC源码分析-集合篇(九)SynchronousQueue
JDK8 的并发编程包中的 SynchronousQueue 是一个没有数据缓冲的 BlockingQueue,生产者线程对其的插入操作 put 必须等待消费者的移除操作 take,反过来也一样。
SynchronousQueue 可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队列本身并不存储任何元素,非常适合传递性场景。SynchronousQueue 的吞吐量高于 LinkedBlockingQueue 和 ArrayBlockingQueue。
1. SynchronousQueue 实现原理
SynchronousQueue 实现原理参考:http://ifeve.com/java-synchronousqueue/
1.1 阻塞算法实现
阻塞算法实现通常在内部采用一个锁来保证多个线程中的 put() 和 take() 方法是串行执行的。采用锁的开销是比较大的,还会存在一种情况是线程 A 持有线程 B 需要的锁,B 必须一直等待 A 释放锁,即使 A 可能一段时间内因为 B 的优先级比较高而得不到时间片运行。所以在高性能的应用中我们常常希望规避锁的使用。
public class NativeSynchronousQueue<E> {
boolean putting = false;
E item = null;
public synchronized E take() throws InterruptedException {
while (item == null)
wait();
E e = item;
item = null;
notifyAll();
return e;
}
public synchronized void put(E e) throws InterruptedException {
if (e==null) return;
while (putting)
wait();
putting = true;
item = e;
notifyAll();
while (item!=null)
wait();
putting = false;
notifyAll();
}
}
1.2 信号量实现
经典同步队列实现采用了三个信号量,代码很简单,比较容易理解:
public class SemaphoreSynchronousQueue<E> {
E item = null;
Semaphore sync = new Semaphore(0);
Semaphore send = new Semaphore(1);
Semaphore recv = new Semaphore(0);
public E take() throws InterruptedException {
recv.acquire();
E x = item;
sync.release();
send.release();
return x;
}
public void put (E x) throws InterruptedException{
send.acquire();
item = x;
recv.release();
sync.acquire();
}
}
2. SynchronousQueue 实现原理
SynchronousQueue 支持公平访问队列。默认情况下线程采用非公平性策略访问队列。使用以下构造方法可以创建公平性访问的 SynchronousQueue,如果设置为 true,则等待的线程会采用先进先出的顺序访问队列。以 TransferQueue 为例
参考:
每天用心记录一点点。内容也许不重要,但习惯很重要!