转载

JDK源码分析-LinkedBlockingQueue

概述

前文「 JDK源码分析-ArrayBlockingQueue 」分析了 ArrayBlockingQueue 的代码实现,LinkedBlockingQueue 也是阻塞队列的实现。与前者不同的是,后者内部是由链表实现的。

LinkedBlockingQueue 的继承结构如下:

JDK源码分析-LinkedBlockingQueue

下面分析其主要方法的代码实现。

代码分析

LinkedBlockingQueue  内部有一个嵌套类 Node,它表示链表的节点,如下:

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">static <span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">class</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">Node</span>&lt;E&gt; {</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> E item; <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">//</span> 节点元素</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> Node&lt;E&gt; <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">next</span>; <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">//</span> 后继节点</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> </span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> Node(E x) { item = x; }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

PS: 从 Node 定义可以看出该链表是一个单链表。

主要成员变量

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 链表的容量(若不指定则为 Integer.MAX_VALUE)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> int capacity;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 当前元素的数量(即链表中元素的数量)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> AtomicInteger count = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> AtomicInteger();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 链表的头节点(节点元素为空)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">transient Node&lt;E&gt; head;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 链表的尾结点(节点元素为空)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> transient Node&lt;E&gt; last;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// take、poll 等出队操作持有的锁</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> ReentrantLock takeLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> ReentrantLock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">/** Wait queue for waiting takes */</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 出队锁的条件队列</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> Condition notEmpty = takeLock.newCondition();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// put、offer 等入队操作的锁</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> ReentrantLock putLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> ReentrantLock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">/** Wait queue for waiting puts */</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 入队锁的条件队列</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> Condition notFull = putLock.newCondition();</span>

构造器

LinkedBlockingQueue 有三个构造器,分别如下:

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 构造器 1:无参构造器,初始容量为 Integer.MAX_VALUE,即 2^31-1</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">LinkedBlockingQueue</span>()</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>(Integer.MAX_VALUE);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 构造器 2:指定容量的构造器</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">LinkedBlockingQueue</span>(<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">int</span> capacity</span>)</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (capacity &lt;= <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>) <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throw</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> IllegalArgumentException();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.capacity = capacity;</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 初始化链表的头尾节点</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> last = head = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> Node&lt;E&gt;(<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><br style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;" /></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 构造器 3:用给定集合初始化的构造器</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">LinkedBlockingQueue</span>(<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">Collection&lt;? extends E&gt; c</span>)</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 调用构造器 2 进行初始化</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>(Integer.MAX_VALUE);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> final ReentrantLock putLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.putLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">lock</span>(); <span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// Never contended, but necessary for visibility</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">int</span> n = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">for</span> (E e : c) {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (e == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throw</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> NullPointerException();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (n == capacity)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throw</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> IllegalStateException(<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">&quot;Queue full&quot;</span>);</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 将集合中的元素封装成 Node 对象,并添加到链表末尾</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> enqueue(<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> Node&lt;E&gt;(e));</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> ++n;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> count.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">set</span>(n);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">finally</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

enqueue 方法如下:

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 将 node 节点添加到链表末尾</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">void</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">enqueue</span>(<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">Node&lt;E&gt; node</span>)</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> last = last.next = node;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

主要入队方法 :put(E)、 offer(E, timeout, TimeUnit) 、offer(E)

1. put(E) 代码如下:

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">void</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">put</span><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">(E e)</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throws</span> InterruptedException </span>{</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (e == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>) <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throw</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> NullPointerException();</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // Note: convention in all put/take/etc is to preset local var</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // holding count negative to indicate failure unless set.</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">int</span> c = -<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>;</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 把 E 封装成 Node 节点</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> Node&lt;E&gt; node = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> Node&lt;E&gt;(e);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> ReentrantLock putLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.putLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> AtomicInteger count = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.count;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.lockInterruptibly();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> /*</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> * Note that count is used in wait guard even though it is</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> * not protected by lock. This works because count can</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> *&gt;<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> * out by lock), and we (or some other waiting put) are</span></span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> * signalled if it ever changes from capacity. Similarly</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> * for all other uses of count in other wait guards.</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> */</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 若队列已满,notFull 等待(类比生产者)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">while</span> (count.get() == capacity) {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notFull.await();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // node 入队</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> enqueue(node);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> c = count.getAndIncrement();</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 若该元素添加后,队列仍未满,唤醒一个其他生产者线程</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (c + <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span> &lt; capacity)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notFull.signal();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">finally</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // c==0 说明之前队列为空,出队线程处于等待状态,</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 添加一个元素后,将出队线程唤醒(消费者)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (c == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> signalNotEmpty();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

signalNotEmpty 方法:

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">void</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">signalNotEmpty</span>()</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> final ReentrantLock takeLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.takeLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">lock</span>();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 唤醒 notEmpty 条件下的一个线程(消费者)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notEmpty.signal();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">finally</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

2. offer(E, timeout, TimeUnit):

<span style=";margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;;margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">boolean</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">offer</span><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">(E e, <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">long</span> timeout, TimeUnit unit)</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throws</span> InterruptedException </span>{</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (e == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>) <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throw</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> NullPointerException();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">long</span> nanos = unit.toNanos(timeout);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">int</span> c = -<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> ReentrantLock putLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.putLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> AtomicInteger count = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.count;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.lockInterruptibly();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">while</span> (count.get() == capacity) {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 等待超时,返回 false</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (nanos &lt;= <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">false</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nanos = notFull.awaitNanos(nanos);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 入队</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> enqueue(<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">new</span> Node&lt;E&gt;(e));</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> c = count.getAndIncrement();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (c + <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span> &lt; capacity)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notFull.signal();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">finally</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (c == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> signalNotEmpty();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">true</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

该方法与 put 操作类似,不同的是 put 方法在队列满时会一直等待,而该方法有超时时间,超时后返回 false。

3. offer(E):

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> boolean offer(<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">E</span> e) {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (e == null) <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throw</span> new <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">NullPointerException</span>();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">AtomicInteger</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span> = this.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>;</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 若队列已满,直接返回 false</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">get</span>() == capacity)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">false</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> int <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> = -<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">Node</span>&lt;<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">E</span>&gt; node = new <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">Node</span>&lt;<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">E</span>&gt;(e);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">ReentrantLock</span> putLock = this.putLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.lock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列未满,入队</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">get</span>() &lt; capacity) {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> enqueue(node);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>.getAndIncrement();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> + <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span> &lt; capacity)</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列未满,唤醒 notFull 下的线程,继续入队</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notFull.signal();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } finally {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> signalNotEmpty();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> &gt;= <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

入队方法小结

1. put(E): 若队列已满,则等待, 无返回值

2.  offer(E, timeout, TimeUnit): 与 put 方法类似,有超时等待和返回值;

3.  offer(E): 立即返回,没有循环等待。

常用出队方法 :take、poll(timeout, TimeUnit)、poll()、peek()

1. take():

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">E</span> take() <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throws</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">InterruptedException</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">E</span> x;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> int <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> = -<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">AtomicInteger</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span> = this.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">ReentrantLock</span> takeLock = this.takeLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.lockInterruptibly();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列为空,notEmpty 条件下的线程等待(消费者)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">while</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">get</span>() == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>) {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notEmpty.await();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 从队列头部删除节点</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> x = dequeue();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>.getAndDecrement();</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 若队列不为空,唤醒一个 notEmpty 条件下的线程(消费者)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> &gt; <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notEmpty.signal();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } finally {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列已经不满了,唤醒 notFull 条件下的线程(生产者)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> == capacity)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> signalNotFull();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> x;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

dequeue 方法:

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> E <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">dequeue</span>()</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> Node&lt;E&gt; h = head; <span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 头节点</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> Node&lt;E&gt; first = h.next; <span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 头节点的后继节点</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> h.next = h; <span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// help GC // 后继节点指向自己(从链表中删除)</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> head = first; <span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 更新头节点</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> E x = first.item; <span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 获取要删除节点的数据</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> first.item = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>; <span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;">// 清空数据(新的头节点)</span></span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> x;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

signalNotFull: 

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">private</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">void</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">signalNotFull</span>()</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> final ReentrantLock putLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.putLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">lock</span>();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 唤醒生产者</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notFull.signal();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">finally</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> putLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

2. poll(timeout, TimeUnit) :

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> E <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">poll</span><span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">(<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">long</span> timeout, TimeUnit unit)</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">throws</span> InterruptedException </span>{</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> E x = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">int</span> c = -<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">long</span> nanos = unit.toNanos(timeout);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> AtomicInteger count = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.count;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> ReentrantLock takeLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.takeLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.lockInterruptibly();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列已空</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">while</span> (count.get() == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>) {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 超时返回 null</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (nanos &lt;= <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> nanos = notEmpty.awaitNanos(nanos);</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> x = dequeue();</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 若队列不空,唤醒一个 notEmpty 条件下的线程(消费者)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> c = count.getAndDecrement();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (c &gt; <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notEmpty.signal();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">finally</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列不满,唤醒 notFull 条件下的线程(生产者)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (c == capacity)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> signalNotFull();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> x;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

与 take 方法类似,多了超时等待。

3. poll():

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">E</span> poll() {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">AtomicInteger</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span> = this.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>;</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列为空,返回 null</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">get</span>() == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> null;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">E</span> x = null;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> int <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> = -<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">ReentrantLock</span> takeLock = this.takeLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.lock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列不为空,出队</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">get</span>() &gt; <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>) {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> x = dequeue();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">count</span>.getAndDecrement();</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 该元素出队后,队列仍不为空,唤醒其他消费者</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> &gt; <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">1</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> notEmpty.signal();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } finally {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 队列已经不满,唤醒生产者</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">c</span> == capacity)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> signalNotFull();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> x;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

4. peek()

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"><span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">public</span> E peek() {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (count.<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">get</span>() == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">0</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">final</span> ReentrantLock takeLock = <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">this</span>.takeLock;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.lock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">try</span> {</span>

<span style="padding:0px;margin:0px;max-width:1000%;font-style:italic;box-sizing:border-box !important;overflow-wrap:break-word !important;"> // 头节点的后继节点</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> Node&lt;E&gt; first = head.next;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">if</span> (first == <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>)</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">null</span>;</span>

<span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;"> else</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">return</span> first.item;</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> } <span style="padding:0px;margin:0px;max-width:1000%;box-sizing:border-box !important;overflow-wrap:break-word !important;">finally</span> {</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> takeLock.unlock();</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> }</span>

<span style="margin: 0px; padding: 0px; max-width: 1000%; box-sizing: border-box !important; overflow-wrap: break-word !important;">}</span>

peek() 方法只返回头节点,并不删除。严格来说该方法并不属于出队操作,只是查询。

出队方法小结

1. take():  获取 队列头部 元素,并将 其移除 ,队列为空时 阻塞等待;

2.  poll(long, unit):  获取队列头部元素,并将其移除 ,队列为空时等待一段时间,若超时返回 null;

3 . poll() : 获取队列头 部元素,并将其移除,队列为空时返回 null;

小结

1. LinkedBlockingQueue 是基于单链表的阻塞队列实现,它在初始化时可以指定容量,若未指定,则默认容量为 Integer.MAX_VALUE;

2. 内部使用了 ReentrantLock 保证线程安全;

3. 常用方法:

入队:put, offer

出队:take, poll, peek

LinkedBlockingQueue  与 ArrayBlockingQueue 比较:

1. ArrayBlockingQueue 使用单个锁,可以指定是否公平;而  LinkedBlockingQueue 内部使用了两个锁:putLock 和 takeLock,都是非公平锁。

2. 入队出队区别

入队时, LinkedBlockingQueue  会判断当前元素入队后,队列是否已满,若未满,则唤醒其他生产者线程;而入队后,当队列之前为空时才唤醒其他消费者线程。ArrayBlockingQueue 则是每次入队都会唤醒消费者线程。

出队时, LinkedBlockingQueue  会判断当前元素出队后,队列是否已空,若未空,则唤醒其他消费者线程; 而出队后, 当队列之前为满时才唤醒其他生产者线程。 ArrayBlockingQueue 则是每次出队都会唤醒生产者线程。

Stay hungry, stay foolish.

JDK源码分析-LinkedBlockingQueue

原文  https://juejin.im/post/5d614b0a518825121f66187c
正文到此结束
Loading...