“死磕”J.U.C系列-18-LinkedBlockingQueue

原理介绍

一个由链表(单向链表)结构组成的有界阻塞队列。此队列的默认和最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。

双锁(ReentrantLock):takeLock、putLock,允许读写并行.

原理图

源码分析

类图

类图

核心方法

入队

offer(E e)

向队列尾部插入一个元素,如果队列有空闲容量则插入成功后返回 true,如果队列已满则丢弃当前元素然后返回false。该方法是非阻塞的,直接返回。

put(E e)

向队列尾部插入一个元素,如果队列有空闲则插入后直接返回true,如果队列已满则阻塞当前线程直到队列有空闲插入成功后返回true,如果在阻塞的时候被其它线程设置了中断标志,则被阻塞线程会抛出 InterruptedException 异常而返回,该方法是阻塞的。

出队

poll()

从队列头部获取并移除一个元素,如果队列为空则返回 null,该方法是不阻塞的。

take()

获取当前队列头部元素并从队列里面移除,如果队列为空则阻塞调用线程,直到队列不为空然后返回元素.如果在阻塞的时候被其它线程设置了中标志,则被阻塞线程会抛出InterruptedException 异常而返回。

remove(Object o)

删除队列里面指定元素,有则删除返回 true,没有则返回false。

获取

peek()

获取队列头部元素但是不从队列里面移除,如果队列为空则返回 null,该方法是不阻塞的。

FAQ

peek()中获取到first节点后,还要判断first是否为null?

判断队列是否为空和获取锁的过程不是原子操作,可能在获取takeLock之前,其他线程执行了poll或take操作,导致队列为空。

LinkedBlockingQueue与ArrayBlockingQueue的比较

ArrayBlockingQueue中在入队列和出队列操作过程中,使用的是同一个lock,读取和操作的都无法做到并行;LinkedBlockingQueue读取和插入操作所使用的锁是两个不同的lock,它们之间的操作互相不受干扰,因此两种操作可以并行完成。

LinkedBlockingQueue相比ArrayBlockingQueue具有更好的扩容性。ArrayBlockingQueue容量固定,可以更好的对吸能进行预测;LinkedBlockingQueue不指定,默认Integer.MAX_VALUE。创建节点是动态地,节点出队列会被GC回收,一种程度上可以理解为“无界队列”。任务多时,入队处理,可能会出现内存溢出的情况。

参考资料:

https://blog.csdn.net/u010887744/article/details/73010691

https://www.jianshu.com/p/cc2281b1a6bc

彩蛋:

对于经常逛github的猿猿(媛媛)们,octotree这个Chrome插件,使得github给人一种IDE的感觉,快来试试吧。

效果图:

资源地址:https://github.com/buunguyen/octotree

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180526G1L7Z800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励