ConcurrentLinkedQueue和LinkedBlockingQueue区别

原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11394436.html

 

线程安全队列类图


两者的区别在于

  • ConcurrentLinkedQueue基于CAS的无锁技术,不需要在每个操作时使用锁,所以扩展性表现要更加优异,在常见的多线程访问场景,一般可以提供较高吞吐量。
  • LinkedBlockingQueue内部则是基于锁,并提供了BlockingQueue的等待性方法。

BlockingQueue基本都是基于锁实现,比如典型的LinkedBlockingQueue


 

有界队列

  • ArrayBlockingQueue是最典型的的有界队列,其内部以final的数组保存数据,数组的大小就决定了队列的边界,所以我们在创建ArrayBlockingQueue时,都要指定容量,如
public ArrayBlockingQueue(int capacity, boolean fair) 
  • LinkedBlockingQueue,容易被误解为无边界,但其实其行为和内部代码都是基于有界的逻辑实现的,只不过如果我们没有在创建队列时就指定容量,那么其容量限制就自动被设置为Integer.MAX_VALUE,成为了无界队列。
  • SynchronousQueue,这是一个非常奇葩的队列实现,每个删除操作都要等待插入操作,反之每个插入操作也都要等待删除动作。那么这个队列的容量是多少呢?是1吗?其实不是的,其内部容量是0。

 

无界队列

  • PriorityBlockingQueue是无边界的优先队列,虽然严格意义上来讲,其大小总归是要受系统资源影响。
  • DelayedQueue和LinkedTransferQueue同样是无边界的队列。对于无边界的队列,有一个自然的结果,就是put操作永远也不会发生其他BlockingQueue的那种等待情况。

 

有界队列使用场景

以LinkedBlockingQueue、ArrayBlockingQueue和SynchronousQueue为例,根据需求可以从很多方面考量:

  • 考虑应用场景中对队列边界的要求。ArrayBlockingQueue是有明确的容量限制的,而LinkedBlockingQueue则取决于我们是否在创建时指定,SynchronousQueue则干脆不能缓存任何元素。
  • 从空间利用角度,数组结构的ArrayBlockingQueue要比LinkedBlockingQueue紧凑,因为其不需要创建所谓节点,但是其初始分配阶段就需要一段连续的空间,所以初始内存需求更大。
  • 通用场景中,LinkedBlockingQueue的吞吐量一般优于ArrayBlockingQueue,因为它实现了更加细粒度的锁操作。
  • ArrayBlockingQueue实现比较简单,性能更好预测,属于表现稳定的“选手”。
  • 如果需要实现的是两个线程之间接力性(handoff)的场景,可能会选择CountDownLatch,但是SynchronousQueue也是完美符合这种场景的,而且线程间协调和数据传输统一起来,代码更加规范。
  • 可能令人意外的是,很多时候SynchronousQueue的性能表现,往往大大超过其他实现,尤其是在队列元素较小的场景。

 

Reference

https://time.geekbang.org/column/article/9588

posted @ 2019-08-22 15:12  李白与酒  阅读(4429)  评论(0编辑  收藏  举报