LinkedBlockingQueue的put方法底层源码
一、LinkedBlockingQueue的put方法底层源码
LinkedBlockingQueue 的 put 方法是其核心方法之一,用于将元素插入队列。如果队列已满,调用 put 方法的线程会被阻塞,直到队列有空闲空间
1、put 方法的作用
-
将元素插入队列尾部。
-
如果队列已满,当前线程会被阻塞,直到队列有空闲空间。
-
该方法不会返回任何值,也不会抛出异常(除非线程被中断)。
2、put 方法的作用
以下是 LinkedBlockingQueue 中 put 方法的源码(基于 JDK 17):

3、源码解析
(1)参数检查

- LinkedBlockingQueue 不允许插入 null 元素,如果传入 null,会抛出 NullPointerException。
(2)创建新节点

- 将元素封装为一个 Node 节点,Node 是 LinkedBlockingQueue 的内部静态类,用于存储队列中的元素
(3)获取锁

-
putLock 是 LinkedBlockingQueue 的成员变量,用于控制插入操作的并发访问。
-
lockInterruptibly() 方法会尝试获取锁,如果线程被中断,会抛出 InterruptedException。
(4)检查队列是否已满

-
count 是一个 AtomicInteger,表示当前队列中的元素数量。
-
如果队列已满(count.get() == capacity),当前线程会调用 notFull.await() 进入等待状态,直到队列有空闲空间。
-
notFull 是一个 Condition 对象,用于实现生产者线程的阻塞和唤醒。
(5)插入元素

- enqueue 方法将新节点插入队列尾部:

last 是队列的尾节点,last.next = node 将新节点链接到队列尾部。
然后更新 last 指向新节点。
(6)更新元素数量

- 使用 AtomicInteger 的 getAndIncrement 方法将队列元素数量加 1,并返回加 1 之前的值(c)
(7)唤醒其他生产者线程

- 如果插入后队列未满(c + 1 < capacity),调用 notFull.signal() 唤醒其他可能正在等待的生产者线程
(8)释放锁

- 在 finally 块中释放锁,确保锁一定会被释放,避免死锁
(9)唤醒消费者线程

-
如果队列中有一条数据(c == 0),调用 signalNotEmpty() 唤醒可能正在等待的消费者线程。
-
signalNotEmpty() 的实现:

获取 takeLock,然后调用 notEmpty.signal() 唤醒消费者线程
二、示例流程图
以下是 put 方法的执行流程图:
1、检查元素是否为 null。
2、创建新节点。
3、获取 putLock。
4、检查队列是否已满:
- 如果满,等待 notFull 条件
5、将节点插入队列尾部。
6、更新元素数量。
7、如果队列未满,唤醒其他生产者线程。
8、释放 putLock。
9、如果队列中有一条数据,唤醒消费者线程。

浙公网安备 33010602011771号