ArrayBlockingQueue的poll方法底层原理

一、ArrayBlockingQueue的poll方法底层原理

ArrayBlockingQueue 是 Java 并发包 (java.util.concurrent) 中的一个基于数组实现的有界阻塞队列。它的 poll() 方法是用于从队列中移除并返回队首元素的核心方法之一。与 take() 方法不同,poll() 方法在队列为空时不会阻塞,而是立即返回 null。


1、poll() 方法的功能

  • 作用:移除并返回队列的队首元素。

  • 非阻塞行为:如果队列为空,立即返回 null,不会阻塞当前线程。

  • 线程安全:poll() 方法是线程安全的,内部通过锁机制实现同步。


2、poll() 方法的源码分析

以下是 ArrayBlockingQueue 中 poll() 方法的源码(基于 JDK 17):


关键点解析


1、获取锁:

  • 使用 lock.lock() 获取锁,确保线程安全。

  • 如果锁被其他线程持有,当前线程会阻塞,直到获取锁。


2、检查队列是否空:

  • 如果队列空(count == 0),直接返回 null。

  • 如果队列非空,调用 dequeue() 方法移除并返回队首元素。


3、释放锁:

  • 在 finally 块中释放锁,确保锁一定会被释放,避免死锁。


3、dequeue() 方法的源码分析

dequeue 是 poll() 方法中用于实际移除元素的私有方法。以下是其源码:


关键点解析


1、获取队首元素:

  • 从数组的 takeIndex 位置获取队首元素。

  • takeIndex 是下一个移除元素的位置。


2、清除队首元素:

  • 将 takeIndex 位置的元素设置为 null,帮助垃圾回收。


3、更新 takeIndex:

  • 如果 takeIndex 达到数组长度,将其重置为 0,实现循环数组的效果。


4、更新元素数量:

  • count 表示队列中的元素数量,移除成功后递减。


5、唤醒生产者线程:

  • 调用 notFull.signal() 唤醒等待 notFull 条件的生产者线程。


4、poll() 方法的非阻塞机制


poll() 方法的非阻塞行为是通过直接检查队列是否空来实现的。如果队列空,立即返回 null,不会调用 await() 方法阻塞当前线程。


5、poll() 方法的性能优化

  • 循环数组:

    • ArrayBlockingQueue 使用循环数组存储元素,避免了数组的频繁扩容和数据拷贝。

    • 通过 putIndex 和 takeIndex 实现队列的循环利用。

  • 锁分离:

    • 使用单独的 Condition 对象(notFull 和 notEmpty)分别管理生产者和消费者的等待队列,减少锁竞争。
  • 公平性:

    • 可以通过构造函数指定是否使用公平锁。公平锁会按照线程等待的顺序分配锁,避免线程饥饿。


二、总结

ArrayBlockingQueue 的 poll() 方法通过以下机制实现了线程安全的非阻塞移除:

1、锁机制:使用 ReentrantLock 保证线程安全。

2、非阻塞行为:如果队列空,立即返回 null,不会阻塞当前线程。

3、循环数组:通过循环数组高效管理队列元素。

posted @ 2025-02-19 01:58  jock_javaEE  阅读(65)  评论(0)    收藏  举报