[核心技术36问]20.并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?

20.并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?

    有时候我们把并发包下面的所有容器都习惯叫做并发容器,但是严格来讲,类似ConcurrentLinkedQueue这种Concurrent*容器,才是真正代表并发。

  • Concurrent类型基于lock-free,在常见的多线程访问场景,一般可以提供较高吞吐量;
  • 而LinkedBlockingQueue内部则是基于锁,并提供了BlokingQueue的等待性方法。

    java.util.concurrent包提供的容器(Queue、List、Set),Map,从名字上可以大概区分为Concurrent,CopyOnWrite,Blocking*等三类,同样是线程安全容器,可以简单认为:

  • Concurrent类型没有CopyOnWrite之类容器相对较重的修改开销;
  • 但是,凡事都是有代价的,Concurrent提供了较低的遍历一致性。即Concurrent是弱一致性的,当利用迭代器遍历时,如果容器发生修改,迭代器仍然可以继续遍历;
  • 与弱一致性相对应的,就是同步容器常见的行为“fast-fail”,也就是检测到容器在遍历过程中发生了修改,则抛出“ConcurrentModificationException”,不再继续遍历;
  • 弱一致性另外一个体现就是size等操作准确性是有限的,未必是100%正确;
  • 与此同时,读取的性能具有一定的不确定性。

理解ConcurrentLinkedDeque和LinkedBlockingQueue的主要功能区别:

    常见的集合如LinkedList是个Deque,只不过不是线程安全的。有两个特别的Deque实现,ConcurrentLikedDeque和LinkedBlockingQueue。Deque的重点是支持对队列头尾都进行插入和删除,所以提供了特定的方法,如:

  • 尾部插入addLast(e),offerLast(e);
  • 尾部删除removeLast(e),pollLast(e);

    从行为上看,绝大部分Queue都实现了BlockingQueue接口。在常规队列操作上,Blocking意味着其提供了特定的等待性操作,获取(take)时等待队列进队,或者插入(put)时等待队列出现空位。

    另一个BlockingQueue经常被考察的点就是是否有界。

  • ArrayBlockingQueue是最典型的有界队列,其内部以final的数组保存数据,数组的大小就决定了队列的边界,所以在创建ArrayBlockingQueue时,都要指定容量;
  • LinkedBlockingQueue,容易被误解为无界队列,但其实其行为和内部代码都是基于有界的逻辑实现的,只不过如果我们没有在创建队列时就指定容量,那么其容量限制就自动被设置为Integer.MAX_VALUE,成为了无界队列;
  • SynchronousQueue,每个删除操作要等待插入操作,每个插入操作也要等待删除操作,内部容量为0;
  • PriorityBlockingQueue是无边界的优先队列,虽然严格意义上来讲,其大小也要受到系统资源影响。
  • DelayedQueue和LinkedTransferQueue同样是无边界队列,对于无边界队列来说,有一个自然的结果,就是put操作永远不会发生像其他BlockingQueue那种等待情况。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值