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
强者自救 圣者渡人