BlockingQueue---ArrayBlockingQueue
总结
队列是有界的,即在创建时必须指定容量,并且该容量是不可变的。
FIFO;
内部使用数组来存储元素,并通过重入锁(ReentrantLock)和条件变量(Condition)来控制并发访问。
特性
- 有界:队列大小固定,在构造时需要指定。
- 阻塞:当队列满时,尝试添加元素的操作会被阻塞,直到队列中有空间;同样,当队列为空时,尝试取元素的操作也会被阻塞,直到队列中有元素。
- 线程安全:可以被多个生产者线程和消费者线程共享,不需要额外的同步机制。
- 公平性选项:可以设置为公平或非公平模式。如果设置为公平模式,那么等待时间最长的线程会优先得到执行机会。
构造函数
ArrayBlockingQueue(int capacity)
: 创建一个具有给定容量但不公平的ArrayBlockingQueue
。ArrayBlockingQueue(int capacity, boolean fair)
: 创建一个具有给定容量并可选择是否公平的ArrayBlockingQueue
。ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c)
: 用给定集合中的元素初始化队列,并允许选择公平性。
方法
- 插入操作:
put(E e)
: 将指定的元素插入此队列尾,如果队列已满,则等待可用的空间。offer(E e)
: 尝试将指定的元素插入此队列尾,如果队列已满,则立即返回false
。offer(E e, long timeout, TimeUnit unit)
: 尝试将指定的元素插入此队列尾,最多等待指定的时间,如果超时队列仍然没有空间则返回false
。
- 移除操作:
take()
: 检索并移除此队列的头,如果队列为空,则等待有元素可用。poll()
: 检索并移除此队列的头,如果队列为空,则立即返回null
。poll(long timeout, TimeUnit unit)
: 检索并移除此队列的头,如果队列为空,则最多等待指定的时间,如果超时队列仍然为空则返回null
。
- 检查操作:
peek()
: 检索但不移除此队列的头;如果队列为空,则返回null
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable { final Object[] items; int takeIndex; int putIndex; final ReentrantLock lock ; public ArrayBlockingQueue( int capacity) { this (capacity, false ); } public ArrayBlockingQueue( int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); this .items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock .newCondition(); notFull = lock .newCondition(); } public boolean offer(E e) { checkNotNull(e); final ReentrantLock lock = this . lock ; lock . lock (); try { if (count == items.length) return false ; else { enqueue(e); return true ; } } finally { lock .unlock(); } } private void enqueue(E x) { // assert lock.getHoldCount() == 1; // assert items[putIndex] == null; final Object[] items = this .items; items[putIndex] = x; if (++putIndex == items.length) putIndex = 0; count++; notEmpty.signal(); } public E poll() { final ReentrantLock lock = this . lock ; lock . lock (); try { return (count == 0) ? null : dequeue(); } finally { lock .unlock(); } } private E dequeue() { // assert lock.getHoldCount() == 1; // assert items[takeIndex] != null; final Object[] items = this .items; @SuppressWarnings( "unchecked" ) E x = (E) items[takeIndex]; items[takeIndex] = null ; if (++takeIndex == items.length) takeIndex = 0; count--; if (itrs != null ) itrs.elementDequeued(); notFull.signal(); return x; } } |
概述
A bounded {@linkplain BlockingQueue blocking queue} backed by an array.
This queue orders elements FIFO (first-in-first-out).
The <em>head</em> of the queue is that element that has been on the queue the longest time.
The <em>tail</em> of the queue is that element that has been on the queue the shortest time.
New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue.
由数组支持的有界 BlockingQueue;
此队列按 FIFO(先进先出)对元素进行排序;
队列<em>头部</em>是在队列中停留时间最长的元素。
队列的<em>尾</em>部是队列中停留时间最短的元素。
新元素 插入到队列的 尾部,队列检索操作获取队列末尾的元素;
This is a classic bounded buffer, in which a fixed-sized array holds elements inserted by producers and extracted by consumers.
Once created, the capacity cannot be changed.
Attempts to {@code put} an element into a full queue will result in the operation blocking; attempts to {@code take} an element from an empty queue will similarly block.
这是一个经典的有界缓冲区,其中 固定大小的数组 包含由producers插入并由consumers提取的元素。
一旦创建,就无法更改容量。
尝试将元素put 完整队列将导致操作阻塞; 尝试从空队列中take元素同样会阻塞。
This class supports an optional fairness policy for ordering waiting producer and consumer threads.
By default, this ordering is not guaranteed.
However, a queue constructed with fairness set to {@code true} grants threads access in FIFO order.
Fairness generally decreases throughput but reduces variability and avoids starvation.
此类支持可选的公平性策略,用于对等待的生产者和使用者线程进行 排序。
默认情况下,不保证此排序。
但是,在公平性设置为 {@code true} 的情况下构造的队列按 FIFO 顺序授予线程访问权限。
公平性通常会降低吞吐量,但会减少可变性并避免饥饿;
This class and its iterator implement all of the <em>optional</em> methods of the {@link Collection} and {@link Iterator} interfaces.
链路
offer(E e)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // java.util.concurrent.ArrayBlockingQueue.offer(E) /** * Inserts the specified element at the tail of this queue if it is possible to do so immediately without exceeding the queue's capacity, returning {@code true} upon success and {@code false} if this queue is full. * 在保证队列容量允许的情况下,在队尾插入元素 * This method is generally preferable to method {@link #add}, which can fail to insert an element only by throwing an exception. * offer比add更适合,add可能会导致一个异常 */ public boolean offer(E e) { checkNotNull(e); final ReentrantLock lock = this .lock; lock.lock(); try { if (count == items.length) return false ; else { enqueue(e); return true ; } } finally { lock.unlock(); } } // java.util.concurrent.ArrayBlockingQueue.enqueue /** * Inserts element at current put position,advances, and signals. * Call only when holding lock. 仅持有lock时被调用 */ private void enqueue(E x) { // assert lock.getHoldCount() == 1; // assert items[putIndex] == null; final Object[] items = this .items; items[putIndex] = x; if (++putIndex == items.length) putIndex = 0 ; count++; notEmpty.signal(); } |
poll()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | // java.util.concurrent.ArrayBlockingQueue.poll() public E poll() { final ReentrantLock lock = this .lock; lock.lock(); try { return (count == 0 ) ? null : dequeue(); } finally { lock.unlock(); } } // java.util.concurrent.ArrayBlockingQueue.dequeue private E dequeue() { // assert lock.getHoldCount() == 1; // assert items[takeIndex] != null; final Object[] items = this .items; @SuppressWarnings ( "unchecked" ) E x = (E) items[takeIndex]; items[takeIndex] = null ; if (++takeIndex == items.length) takeIndex = 0 ; count--; if (itrs != null ) itrs.elementDequeued(); notFull.signal(); return x; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)