上篇文章,介绍了 SynchronousQueue
的公平模式(源码分析)。
这篇文章,从源码入手,解析 非公平模式。
如果你对SynchronousQueue不熟悉,可以先看我的这篇文章(图解SynchronousQueue)。
一、初始化
SynchronousQueue<Integer> queue = new SynchronousQueue<>();
public SynchronousQueue() {
this(false);
}
public SynchronousQueue(boolean fair) {
transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
}
也就是,不传参数,或传一个false时,就会实现非公平模式。
内部类 TransferStack
没有带参构造器,看下它的几个属性
static final int REQUEST = 0; // 取元素标识
static final int DATA = 1; // 放元素标识
static final int FULFILLING = 2; // 已匹配标识
// TransferStack的内部类SNode 的几个属性
volatile SNode next; // 栈中下一个元素
volatile SNode match; // 与其匹配的元素
volatile Thread waiter; // 对应的线程
Object item; // 元素的值
int mode;
二、调用 put() 后阻塞
用 图解 SynchronousQueue 那篇文章中的例子。 t1, t2, t3 先后往队列中放 10, 20, 30
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
if (transferer.transfer(e, false, 0) == null) {
Thread.interrupted();
throw new InterruptedException();
}
}
也就是说 put(e) 方法,会调用 transferer.transfer(e, false, 0) 。
顺便说下,取元素与放元素都会调用这个 transfer 方法,只是参数不同而已。
E transfer(E e, boolean timed, long nanos) {
SNode s = null; // constructed/reused as needed
int mode = (e == null) ? REQUEST : DATA;
for (;;) {
SNode h = head;
if (h == null || h.mode == mode) {
// empty or same-mode
if (timed && nanos <= 0) {
// can't wait
if (h != null && h.isCancelled())
casHead(h, h.next); // pop cancelled node
else
return null;
} else if (casHead(h, s = snode(s, e, h, mode))) {
SNode m = awaitFulfill(s, timed, nanos);
if (m == s) {
// wait was cancelled