学习目标
在学习了阻塞队列ArrayBlockingQueue、LinkedBlockingQueue和LinkedBlockingDeque我们对Java的阻塞队列有了一定的认识,有了生产消费者模型基本的概念。但是此时若有这样的场景:
我们想建立一个以生产和消费者为主体的队列,当生产者生产没有被消费时阻塞,消费者消费没有生产数据时也阻塞消费线程。保证生产和消费能够组成CP才能成功
那么本节我们便来学习SynchronousQueue和LinkedTransferQueue达此目的。
SynchronousQueue
我们知道传统的生产消费模型是这样的:
有多个生产者,可以并发生产产品,把产品置入队列中,如果队列满了,生产者就会阻塞;有多个消费者,并发从队列中获取产品,如果队列空了,消费者就会阻塞
而另一种反向压力的实现是:消费者唤醒生产者
其中著名的场景便是线程池
不像ArrayBlockingQueue、LinkedBlockingDeque之类的阻塞队列依赖AQS实现并发操作,SynchronousQueue直接使用CAS实现线程的安全访问,且SynchronousQueue内部没有容器,例如之前的队列或数组存储数据。
我们可以来看看SynchronousQueue的具体实现:
public class SynchronousQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
private static final long serialVersionUID = -3223113410248163686L;
static final int NCPUS = Runtime.getRuntime().availableProcessors();
static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32;
/**
* The number of times to spin before blocking in untimed waits.
* This is greater than timed value because untimed waits spin
* faster since they don't need to check times on each spin.
*/
static final int maxUntimedSpins = maxTimedSpins * 16;
/**
* The number of nanoseconds for which it is faster to spin
* rather than to use timed park. A rough estimate suffices.
*/
static final long spinForTimeoutThreshold = 1000L;
/** Dual Stack*/
static final class TransferStack<E> extends Transferer<E>{
}
/** Dual Queue */