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、如果队列中有一条数据,唤醒消费者线程。

posted @ 2025-02-19 16:00  jock_javaEE  阅读(41)  评论(0)    收藏  举报