问题
输入图片说明
- LinkedBlockingQueue是什么?
- 优缺点?
- 应用场景?
- 源码实现?
- 个人启发?
LinkedBlockingQueue
双向并发阻塞队列。
所谓双向是指可以从队列的头和尾同时操作,并发只是线程安全的实现,阻塞允许在入队出队不满足条件时挂起线程,这里说的队列是指支持FIFO/FILO实现的链表。
- 要想支持阻塞功能,队列的容量一定是固定的,否则无法在入队的时候挂起线程。也就是capacity是final类型的。
- 既然是双向链表,每一个结点就需要前后两个引用,这样才能将所有元素串联起来,支持双向遍历。也即需要prev/next两个引用。
- 双向链表需要头尾同时操作,所以需要first/last两个节点,当然可以参考LinkedList那样采用一个节点的双向来完成,那样实现起来就稍微麻烦点。
- 既然要支持阻塞功能,就需要锁和条件变量来挂起线程。这里使用一个锁两个条件变量来完成此功能。
优缺点
优点当然是功能足够强大,同时由于采用一个独占锁,因此实现起来也比较简单。所有对队列的操作都加锁就可以完成。同时独占锁也能够很好的支持双向阻塞的特性。
凡事有利必有弊。缺点就是由于独占锁,所以不能同时进行两个操作,这样性能上就大打折扣。从性能的角度讲LinkedBlockingDeque要比LinkedQueue要低很多,比CocurrentLinkedQueue就低更多了,这在高并发情况下就比较明显了。
前面分析足够多的Queue实现后,LinkedBlockingDeque的原理和实现就不值得一提了,无非是在独占锁下对一个链表的普通操作。
核心方法
在使用之前,让我们一起看一个简单的例子。
添加元素
移除元素
例子
我们实现 put 和 take,分别模拟写入工作者,和取出工作者。
package com.github.houbb.lock.test.lock;import java.util.concurrent.*;/** * @author binbin.hou * @since 1.0.0 */public class LinkedBlockingQueueDemo { private BlockingQueue queue = new LinkedBlockingQueue<>(3); public void put(final String put) throws InterruptedException { System.out.println("设置开始"); TimeUnit.SECONDS.sleep(1); queue.put(put); System.out.println("设置完成: " + put); } public void take() throws InterruptedException { System.out.println("获取开始"); String take = queue.take(); System.out.println("获取成功: " + take); }}
测试代码:
public static void main(String[] args) { final LinkedBlockingQueueDemo queueTest = new LinkedBlockingQueueDemo(); // 写入线程 new Thread(new Runnable() { @Ove