关于SynchronousQueue的一些随笔v1.1

最近用到了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先执行。通过阅读源码,发现其size()方法返回固定值0,为什么会这样呢?通过本文第3点分析,SynchronousQueue会存储放数据的节点和取数据的节点,这时候获取的长度是无效的,没有任何意义,所以返回了0,但“不存储元素”表述不准确。 

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操作。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值