最近用到了SynchronousQueue,也在网上查阅了相关资料,总感觉有些话说得让人费解,下面结合自己的理解总结下。
1、一个不存储元素的阻塞队列。这句话就让我困惑了,不存储元素,那元素保存到哪里了?通过阅读源码,以非公平模式为例:
...
casHead(h, s = snode(s, e, h, mode))
...
static SNode snode(SNode s, Object e, SNode next, int mode) {
if (s == null) s = new SNode(e);
s.mode = mode;
s.next = next;
return s;
}
...
Thread w = Thread.currentThread();
...
else if (s.waiter == null)
s.waiter = w;
实际上元素还是保存下来了(不考虑take操作,可以暂时理解为链表),而且把调用put方法的线程也保存了。通过调试也可看到SynchronousQueue对象信息:
说明:启用了线程 put-t1放入整型数据1和线程put-t2放入整型数据2,put-t1先执行。
2、SynchronousQueue吞吐量高于LinkedBlockingQueue和ArrayBlockingQueue。这种必然是有前提的,put(生产者)和take(消费者)效率一致。否则,生产者和消费者互相等待,吞吐量会手影响。
3、SynchronousQueue作为一个空集合,此队列不允许 null 元素。对于这句话我同样无法理解,为什么?看看源码,比较put和take操作:
put操作时,...transferer.transfer(e, false, 0)...;
take操作时,...E e = transferer.transfer(null, false, 0)...;
一下子就明白了,如果放入了null,表示这个节点对应的是take操作;放入非null表示这个节点对应的是put操作。