LinkedBlockingDeque是由链表构成的双向队列,可以从队列的两端插入和删除元素。双向队列多了一个端的操作入口,所以在并发时,可以减少一半的竞争。LinkedBlockingDeque比起LinkedBlockingQueue多了操作另一端的方法,所以它的方法offer/put/poll/take是成对的,变成了offerFirst/offerLast/pollFirst/pollLast等。LinkedBlockingDeque可以初始化时指定容量,如果不指定,则为Integer.MAX_VALUE。
   LinkedBlockingDeque的并发控制同样使用非公平锁版本的ReentrantLock和两个Condition对象notFull和notEmpty来实现。
一、LinkedBlockingDeque的结构
   LinkedBlockingDeque的结构由一个内部类Node表示队列中的节点,Node中有prev,next两个引用分别指向前后节点。LinkedBlockingDeque分别由first、last分别代表队列的首结点和尾节点。还有int型的count和capacity代表队列中的元素数量和队列的容量。相关代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | static final class Node<E> {         E item;          Node<E> prev;          Node<E> next;         Node(E x, Node<E> p, Node<E> n) {             item = x;             prev = p;             next = n;         }     }          transient Node<E> first;          transient Node<E> last;          private transient int count;          private final int capacity;          final ReentrantLock lock = new ReentrantLock();          private final Condition notEmpty = lock.newCondition();          private final Condition notFull = lock.newCondition();
  | 
 
二、LinkedBlockingDeque的主要方法实现
LinkedBlockingDeque主要的入队和出队方法都是基于linkFirst/linkLast/unlinkFirst/unlinkLast来实现的。
1、入队操作
   入队操作的方法是成对的,有putFirst/putLast/offerFirst/offerLast等。代码实现比较简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | public void putFirst(E e) throws InterruptedException {         if (e == null) throw new NullPointerException();         final ReentrantLock lock = this.lock;         lock.lock();         try {                          while (!linkFirst(e))                 notFull.await();         } finally {             lock.unlock();         }     }     public void putLast(E e) throws InterruptedException {         if (e == null) throw new NullPointerException();         final ReentrantLock lock = this.lock;         lock.lock();         try {                        while (!linkLast(e))                 notFull.await();         } finally {             lock.unlock();         }    }
  | 
 
2、出队操作 
同样,出队操作也是成对的方法pollFirst/pollLast/takeFirst/takeLast.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | public E takeFirst() throws InterruptedException {         final ReentrantLock lock = this.lock;         lock.lock();         try {             E x;             while ( (x = unlinkFirst()) == null)                 notEmpty.await();             return x;         } finally {             lock.unlock();         }     }     public E takeLast() throws InterruptedException {         final ReentrantLock lock = this.lock;         lock.lock();         try {             E x;             while ( (x = unlinkLast()) == null)                 notEmpty.await();             return x;         } finally {             lock.unlock();         }     }
  | 
 
三、总结
   LinkedBlockingDeque的功能很强大,但使用的是一个独占锁,两头的操作其实都是用同一个锁,所以并发能力理论上不会太高。LinkedBlockingDeque一般运用在工作窃取的场景中,如Fork/Join框架。