关键词:BlockingDeque LinkedBlockingDeque Deque
JDK中对BlockingDeque的实现,只提供了LinkedBlockingDeque基于链表的实现方式。个人的猜测是因为双端队列基于数组实现的话会比较复杂,数组不适合作为双端队列的实现结构。(学习LinkedBlockingDeque前,建议先了解BlockingDeque,请戳《JUC之BlockingDeque双端队列》)
█ LinkedBlockingDeque
字段:
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();
- first
队列中的第一个元素节点,即队首的第一个元素节点。
Node类型的字段,Node是LinkedBlockingDeque中定义的内部类,从定义来看,Node构成的链表是双向链表。
static final class Node<E> {
// 节点对应的元素
E item;
// 该节点的前驱节点
Node<E> prev;
// 该节点的后驱节点
Node<E> next;
Node(E x) {
item = x;
}
}
- last
队列中的最后一个元素节点,即队尾的第一个元素节点。
- count
队列中存在的元素个数。
- capacity
队列的容量,即队列最多能存放的元素个数。
- lock
使用ReentrantLock来保证线程安全。
- notEmpty
使用ReentrantLock的Condition完成线程间的通信,通知正在阻塞等待移出数据的线程,队列不为空了。
- notFull
通知正在阻塞等待添加数据的线程,队列没有满。
构造器:
public LinkedBlockingDeque() {
this(Integer.MAX_VALUE);
}
public LinkedBlockingDeque(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
}
public LinkedBlockingDeque(Collection<? extends E> c) {
this(Integer.MAX_VALUE);
final ReentrantLock lock = this.lock;
lock.lock(); // Never contended, but necessary for visibility
try {
for (E e : c) {
if (e == null)
throw new NullPointerException();
if (!linkLast(new Node<E>(e)))
throw new IllegalStateException("Deque full");
}
} finally {
lock.unlock();
}
}
①在构造器中对队列的容量进行初始化,且容量值必须为大于0的正数。
②默认的容量为Integer.MAX_VALUE。
③当使用Collection初始化队列时,集合中不能含有null元素而且集合中元素的个数不能超过队列的容量,即Integer.MAX_VALUE。
方法:
(方法都是对BlockingDeque或Deque中定义的方法的实现,关于方法具体具有的行为约束,请戳《JUC之BlockingDeque双端队列》)
1、向队列中添加元素(不具有阻塞等待功能)
- offerFirst
向队首添加元素,如果队列满了没有足够的空间继续添加元素,则元素添加失败,返回false。
public boolean offerFirst(E e) {
// 限制元素不能为null
if (e == null) throw new NullPointerException();
// 将元素封装成Node对象
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
return linkFirst(node);
} finally {
lock.unlock();
}
}