java 遍历linkedblockingqueue_Java同步数据结构之LinkedBlockingQueue

前言

比起ArrayBlockingQueue,LinkedBlockingQueue应该是最被大家常用的阻塞队列,LinkedBlockingQueue是基于链表的一种可选容量的阻塞队列,也就是说,在构造LinkedBlockingQueue实例的时候,你可以像ArrayBlockingQueue那样指定队列大小,也可以不指定大小(这时候默认就是Integer.MAX_VALUE),指定队列的大小是为了防止队列过度的扩张,导致内存被过度占用或溢出。链表的节点是在每一次插入时动态的创建的,除非这会导致队列超出容量限制。LinkedBlockingQueue的容量在实例被构造完成之后也是不允许被更改的。

与ArrayBlockingQueue一样LinkedBlockingQueue不允许插入null值,也是先进先出FIFO队列,队列的头部是队列中存在时间最长的元素,新元素被插入到队尾,队列出队从头部开始。与ArrayBlockingQueue相比,LinkedBlockingQueue通常具有更高的吞吐量,但在大多数并发应用程序中性能的可预测性较差。

LinkedBlockingQueue采用了“双锁队列” 算法,元素的入队和出队分别由putLock、takeLock两个独立的可重入锁来实现。所以比起ArrayBlockingQueue明显提高了吞吐量。

源码分析

先看看其成员变量:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 static class Node{2 E item;3

4 /**

5 * One of:6 * - the real successor Node7 * - this Node, meaning the successor is head.next8 * - null, meaning there is no successor (this is the last node)9 */

10 Nodenext;11

12 Node(E x) { item =x; }13 }14

15 /**The capacity bound, or Integer.MAX_VALUE if none*/

16 private final intcapacity;17

18 /**Current number of elements*/

19 private final AtomicInteger count = newAtomicInteger();20

21 /**

22 * Head of linked list.23 * Invariant: head.item == null24 */

25 transient Nodehead;26

27 /**

28 * Tail of linked list.29 * Invariant: last.next == null30 */

31 private transient Nodelast;32

33 /**Lock held by take, poll, etc*/

34 private final ReentrantLock takeLock = newReentrantLock();35

36 /**Wait queue for waiting takes*/

37 private final Condition notEmpty =takeLock.newCondition();38

39 /**Lock held by put, offer, etc*/

40 private final ReentrantLock putLock = newReentrantLock();41

42 /**Wait queue for waiting puts*/

43 private final Condition notFull = putLock.newCondition();

View Code

上面的Node节点内部类显然就是用于实现链表的节点实体,item就是当前节点携带的真正对象,next指向下一个节点。head、last分别表示链表的首尾节点,值得注意的是,在LinkedBlockingQueue内部实现的时候,head节点不会参与到链表的实体绑定,也就是说,真正的有效节点挂载都在head节点之后,所以head.item 永远都为null。takeLock和putLock两把锁以及各自的Condition实例分别用于队列元素的出队和入队,可以看到表示队列当前元素个数的count是由一个原子变量来保存的,这是为了避免在维护该变量的时候需要同时获取takeLock、putLock两个锁。当然LinkedBlockingQueue内部还是有一些方法需要同时获取两个锁才能执行,后面会介绍。

LinkedBlockingQueue实例在构造的时候可以指定容量也可以不指定,另外和ArrayBlockingQueue一样也可以在初始化的时候用一个指定的集合初始化队列:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public LinkedBlockingQueue(intcapacity) {2 if

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值