LinkedBlockingDueue是基于一个双向的链表,可以先进先出(队列),也可以先进后出 (栈)
不允许插入null,基本原理和方法都和LinkedBlockingQueue差不多
public class LinkedBlockingDeque<E>
extends AbstractQueue<E>
implements BlockingDeque<E>, java.io.Serializable {
// node节点
static final class Node<E> {
/**
* The item, or null if this node has been removed.
*/
E item;
/**
* One of:
* - the real predecessor Node
* - this Node, meaning the predecessor is tail
* - null, meaning there is no predecessor
*/
Node<E> prev;
/**
* One of:
* - the real successor Node
* - this Node, meaning the successor is head
* - null, meaning there is no successor
*/
Node<E> next;
Node(E x) {
item = x;
}
}
// 头尾两个节点并没有显式的链接,而且约定链接?
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
// 队列第一个节点,一种情况是头尾节点都是null的时候,另一种是头节点的有值但上一个prev是null
transient Node<E> first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
// 队列尾节点,一种情况是头尾节点都是null的时候,另一种要不就是尾节点有值但下一个next是null
transient Node<E> last;
// 队列元素个数
private transient int count;
// 队列最大容量
private final int capacity;
// 独占锁
/** Main lock guarding all access */
final ReentrantLock lock = new ReentrantLock();
/** Condition for waiting takes */
private final Condition notEmpty = lock.newCondition();
/** Condition for waiting puts */
private final Condition notFull = lock.newCondition();
// 默认容量Integer.MAX_VALUE
public LinkedBlockingDeque() {
this(Integer.MAX_VALUE);
}
// 插入一个元素到队列尾部
public boolean offer(E e) {
return offerLast(e);
}
// 插入一个元素到队列尾部
public boolean offerLast(E e) {
if (e == null) throw new NullPointerException();
// 新建节点
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
// 加锁
lock.lock();
try {
return linkLast(node);
} finally {
lock.unlock();
}
}
// 把节点链接到尾节点的next
private boolean linkLast(Node<E> node) {
// assert lock.isHeldByCurrentThread();
// 如果元素个数达到容量上限就返回false
if (count >= capacity)
return false;
// 把node的前一个指针指向原来的last
Node<E> l = last;
node.prev = l;
// 把插入的node置为新的last节点
last = node;
// 把原来的last节点的next指向node,也就是新的last
// 如果头指针为null,则把尾指针赋值给头指针
if (first == null)
first = node;
else
l.next = node;
// 把元素个数+1
++count;
// 唤醒正在取元素的线程
notEmpty.signal();
return true;
}
// 取一个元素,头节点
public E poll() {
return pollFirst();
}
// 取队列头节点
public E pollFirst() {
final ReentrantLock lock = this.lock;
// 加锁
lock.lock();
try {
return unlinkFirst();
} finally {
lock.unlock();
}
}
// 取走头节点并删除
private E unlinkFirst() {
// assert lock.isHeldByCurrentThread();
Node<E> f = first;
if (f == null)
return null;
// 保存头节点的下一个节点next
Node<E> n = f.next;
// 保存头节点的值
E item = f.item;
// 释放头节点的值,以及自己指向自己断除引用
f.item = null;
f.next = f; // help GC
// 把头节点的下一个节点当作新的头节点
first = n;
// 如果那个节点是null,那就把尾节点也置null
// 否则把头节点的前一个节点置null
if (n == null)
last = null;
else
n.prev = null;
// 元素个数-1
--count;
// 唤醒正在插入元素的线程
notFull.signal();
return item;
}
// 放入一个元素到尾部,如果队列满就阻塞等待
public void put(E e) throws InterruptedException {
putLast(e);
}
public void putLast(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
while (!linkLast(node))
notFull.await();
} finally {
lock.unlock();
}
}
// 从头部获取一个元素并删除,如果队列为空就阻塞并等待
public E take() throws InterruptedException {
return takeFirst();
}
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 void push(E e) {
addFirst(e);
}
public E pop() {
return removeFirst();
}
public void addFirst(E e) {
if (!offerFirst(e))
throw new IllegalStateException("Deque full");
}
public boolean offerFirst(E e) {
if (e == null) throw new NullPointerException();
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
return linkFirst(node);
} finally {
lock.unlock();
}
}
private boolean linkFirst(Node<E> node) {
// assert lock.isHeldByCurrentThread();
// 如果达到容量了就马上返回
if (count >= capacity)
return false;
// 获取头节点
Node<E> f = first;
// 新插入的节点的下一个节点指向头节
node.next = f;
// 把新插入的节点置为头节点
first = node;
// 把原头节点的前一个节点prev指向新插入的node
if (last == null)
last = node;
else
f.prev = node;
// 元素个数+1
++count;
// 唤醒正在取元素的线程
notEmpty.signal();
return true;
}
// 移除头节点
public E removeFirst() {
E x = pollFirst();
if (x == null) throw new NoSuchElementException();
return x;
}
public E pollFirst() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return unlinkFirst();
} finally {
lock.unlock();
}
}
private E unlinkFirst() {
// assert lock.isHeldByCurrentThread();
// 其实就是把头节点的下一个节点当作新的头节点,唤醒等到取元素的线程
Node<E> f = first;
if (f == null)
return null;
Node<E> n = f.next;
E item = f.item;
f.item = null;
f.next = f; // help GC
first = n;
if (n == null)
last = null;
else
n.prev = null;
--count;
notFull.signal();
return item;
}
}