BlockingQueue---LinkedBlockingQueue
总结
LinkedBlockingQueue
基于链表结构实现,FIFO;
可以是有界的也可以是无界的。如果在构造时没有指定容量,那么它默认是一个无界队列;如果指定了容量,则会创建一个有界队列。
使用ReentrantLock控制并发访问;
特性
- 可选有界或无界:可以在构造时指定队列的容量来创建有界队列,如果不指定则为无界。
- 阻塞:当队列满时(对于有界队列),尝试添加元素的操作会被阻塞,直到队列中有空间;同样,当队列为空时,尝试取元素的操作也会被阻塞,直到队列中有元素。
- 线程安全:可以被多个生产者线程和消费者线程共享,不需要额外的同步机制。
- 高并发性能:内部使用两个独立的锁分别控制头尾操作,从而提高了并发访问的性能。
构造函数
LinkedBlockingQueue()
: 创建一个无界的LinkedBlockingQueue
。 Integer.MAX_VALUELinkedBlockingQueue(int capacity)
: 创建一个具有给定容量的LinkedBlockingQueue
。LinkedBlockingQueue(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
。
public class LinkedBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable { static class Node<E> { E item; /** * One of: * - the real successor Node * - this Node, meaning the successor is head.next * - null, meaning there is no successor (this is the last node) */ Node<E> next; Node(E x) { item = x; } } private final int capacity; transient Node<E> head; private transient Node<E> last; private final AtomicInteger count = new AtomicInteger(); private final ReentrantLock putLock = new ReentrantLock(); private final ReentrantLock takeLock = new ReentrantLock(); public LinkedBlockingQueue() { this(Integer.MAX_VALUE); } public LinkedBlockingQueue(int capacity) { if (capacity <= 0) throw new IllegalArgumentException(); this.capacity = capacity; last = head = new Node<E>(null); } public boolean offer(E e) { if (e == null) throw new NullPointerException(); final AtomicInteger count = this.count; if (count.get() == capacity) return false; int c = -1; Node<E> node = new Node<E>(e); final ReentrantLock putLock = this.putLock; putLock.lock(); try { if (count.get() < capacity) { enqueue(node); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); } } finally { putLock.unlock(); } if (c == 0) signalNotEmpty(); return c >= 0; } private void enqueue(Node<E> node) { // assert putLock.isHeldByCurrentThread(); // assert last.next == null; last = last.next = node; } public E poll() { final AtomicInteger count = this.count; if (count.get() == 0) return null; E x = null; int c = -1; final ReentrantLock takeLock = this.takeLock; takeLock.lock(); try { if (count.get() > 0) { x = dequeue(); c = count.getAndDecrement(); if (c > 1) notEmpty.signal(); } } finally { takeLock.unlock(); } if (c == capacity) signalNotFull(); return x; } private E dequeue() { // assert takeLock.isHeldByCurrentThread(); // assert head.item == null; Node<E> h = head; Node<E> first = h.next; h.next = h; // help GC head = first; E x = first.item; first.item = null; return x; } }
概述
An optionally-bounded {@linkplain BlockingQueue blocking queue} based on linked nodes.
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.
Linked queues typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.
基于 node链接 的可选边界 BlockingQueue。
此队列按 FIFO(先进先出)对元素进行排序。
队列<em>头部</em>是在队列中停留时间最长的元素。
队列的<em>尾</em>部是队列中停留时间最短的元素。
新元素插入到队列的尾部,队列检索操作获取队列末尾的元素。
链接队列通常比基于Array的队列具有更高的吞吐量,但在大多数并发应用程序中,性能的可预测性较低。
The optional capacity bound constructor argument serves as a way to prevent excessive queue expansion.
The capacity, if unspecified, is equal to {@link Integer#MAX_VALUE}.
Linked nodes are dynamically created upon each insertion unless this would bring the queue above capacity.
可选的容量参数 为了防止队列过度扩展;
capacity如果未指定,默认是 Integer#MAX_VALUE;
node在每次insert操作时动态链接;
public class LinkedBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable { static class Node<E> { E item; Node<E> next; Node(E x) { item = x; } } /** The capacity bound, or Integer.MAX_VALUE if none */ private final int capacity; transient Node<E> head; private transient Node<E> last; public LinkedBlockingQueue() { this(Integer.MAX_VALUE); } public LinkedBlockingQueue(int capacity) { if (capacity <= 0) throw new IllegalArgumentException(); this.capacity = capacity; last = head = new Node<E>(null); } }