和LinkedBlockQueue类似,LinkedBlockingDeque也是一个基于链表实现的队列,不过是双端队列,队列双端都可以做插入和移除操作,而且实现的是BlockingDeque接口而不是BlockingQeque接口,当然BlockingDeque还是继承自BlockingQeque。

1. 主要成员

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();

节点类:

static final class Node<E> {
E item;// 节点值
Node<E> prev;// 前驱节点
Node<E> next;// 后继节点
Node(E x) {
item = x;
}
}

2. 基本操作

2.1构造方法

public LinkedBlockingDeque() {
this(Integer.MAX_VALUE);// 默认容量是整型最大值,链表,无界队列
}

public LinkedBlockingDeque(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
}

2.2 入队

​offer()方法​

public boolean offer(E e) {
return offerLast(e);// 默认是队尾入队,直接返回入队结果(true/false)
}

public boolean offerLast(E e) {
// offer(e):入队元素e不能是null
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();
}
}

// 尾部入队,直接返回入队结果(true/false)
private boolean linkLast(Node<E> node) {
if (count >= capacity)
return false;
Node<E> l = last;
node.prev = l;
last = node;
if (first == null)
first = node;
else
l.next = node;
++count;
notEmpty.signal();
return true;
}

​put()方法​

public void put(E e) throws InterruptedException {
putLast(e);
}

public void putLast(E e) throws InterruptedException {
// 入队元素同样不能为null
if (e == null) throw new NullPointerException();
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 和put不同的地方在于,只要添加失败就会一直阻塞
while (!linkLast(node))
notFull.await();
} finally {
lock.unlock();
}
}

​add()​

public boolean add(E e) {
addLast(e);// 入队失败,直接抛出异常
return true;
}

public void addLast(E e) {
// 入队失败,直接抛出异常
if (!offerLast(e))
throw new IllegalStateException("Deque full");
}

2.3 出队

​poll()​

public E poll() {
return pollFirst();// 头部出队
}

public E pollFirst() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 实际出队方法:unlinkFirst
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;
}

​remove()​

public E remove() {
return removeFirst();
}

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();
}
}