java queue put offer_Java高并发系列之LinkedBlockingQueue源码解析

本文深入剖析Java并发容器LinkedBlockingQueue的内部实现,包括构造方法、offer、put、poll、take、peek操作的源码分析,揭示其在高并发场景下的工作原理,特别关注其锁策略和线程安全。
摘要由CSDN通过智能技术生成

首先,我们来看一下LinkedBlockingQueue的类图。在LinkedBlockingQueue的内部定义了两把锁,分别是takeLock和putLock,其都是ReentrantLock。其插入和取出元素分别在链表两端进行。

35b0d8f263b64e74d8095d2693e5ae24.png

从类图中可以看出,LinkedBlockingQueue继承了AbstractQueue类,同时实现了BlockingQueue接口。这个和ArrayBlockingQueue一致。下面我们来看看其中的核心实现及源码。

1、构造方法

构造函数有两个,分别是无参构造函数和有参数构造函数。其中无参构造函数调用的还是这个有参构造函数,传入的参数为Integer.Max_Value。下面来看看有参构造函数。一般LinkedBlockingQueue是***队列(因为链表节点可以动态增加,不像数组初始化定死了容量)。从这这里设置的最大容量来看,LinkedBlockingQueue也算有界队列。

e8ff65b2b22bcda683e6585ae8e6a942.png

2、offer操作

offer操作是入队一个元素,在LinkedBlockingQueue中定义了两个哨兵节点,分别是head和tail。添加元素的时候就从tail往后加。取出元素的时候是从head节点开始的。(注意:head节点实际上不存储元素,队首其实是head.next)

536a6e1754f0c220ae5628dbdbe01a5d.png

从源码的角度来看,首先判断当前元素个数是否达到设定容量。如果是,则直接返回false。否则,会获取putLock进行加锁,然后在元素head后面添加元素,最后释放锁。这里注意两点,第一,在获取锁后再次进行判断当前元素个数是否小于capacity,是因为在获取锁之前,可能有其他线程进行了offer操作。第二,元素入队之后 判断元素+1小于capacity,然后唤醒notFull队列,这是因为有可能有线程在队列满了然后执行put操作而阻塞挂起。

3、put操作

put操作也是向队列中添加一个元素。源码如下:

put操作的首先会检查压入元素是否为空,不为空则继续进行。然后获取锁,如果当前队列已经达到设定的capacity,那么就阻塞自己挂起当前线程等待唤醒。如果队列没有满,则进行入队操作。最后还是要看看唤醒notFull阻塞的线程。最后,释放锁。另外,put操作是可以响应中断的。

3、poll操作

poll操作是从队列取走一个元素,这里是从队列的head节点下一个节点开始取元素。源码如下:

e13e13711a83b8b20a3e1a2b06d0e35e.png

从源码可以看出,poll操作首先会检查队列是否为空,如果为空则直接返回null。否则,获取锁,然后再次判断元素个数是否大于0,这里是二次判断,防止在上面获取锁之前有线程抢断本线程,执行了poll操作取走元素造成队列为空。最后,判断c==capacity,说明取走了一个元素,当前队列最少空一个位置。那么就可以唤醒因为执行put方法被阻塞(该线程因队列满而被挂起)的线程。注意,poll方法是非阻塞的。

4、take操作

take的操作也是从队列首取走一个元素,其源码如下:

75c18ec8e5f5bf42cef37b335a0a645b.png

从源码可以看出,首先获取队列元素个数,然后加锁。当线程元素为0,那么就无法取走元素,需要阻塞并挂起当前线程(直到put或poll方法执行,队列中有元素了,该线程才被唤醒)。最后,还是判断c==capacity,这里c是线程取走元素之前的长度(count调用的是getAndDecrement方法,先返回当前值然后减1)。注意,此方法也是响应中断的,也就是可以被中断的。

5、peek操作

peek操作是查看在队列头部元素而不删除。源码如下所示:

e31a435336933fe376c2f3c9865fc046.png

从源码上可以看出,peek操作也是非阻塞式的,这里head节点是哨兵节点,真正的头节点是head的下一个节点。如果队列头部元素为null,则返回null。否则返回队首的元素值。

6、size操作

由于定义count为AtomicInteger类型,因此返回的size是准确的。源码如下所示:

94645475684606dbc8664098194d2b89.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值