一、简介
1.LinkedBlockingDeque是基于双向链表实现的并发阻塞队列。支持FIFO和FILO两种操作方式。
2.LinkedBlockingDeque继承了AbstractQueue,实现BlockingDeque接口。也就是支持多线程并发。
二、 属性
//链表的头结点
transient Node<E> first;
//链表的尾节点
transient Node<E> last;
//链表的实际元素个数
private transient int count;
//链表的最大容量个数
private final int capacity;
//线程锁
final ReentrantLock lock = new ReentrantLock();
//队列链表为空时,阻塞tabke的队列条件。
private final Condition notEmpty = lock.newCondition();
//队列链表满了是,阻塞put的队列。
private final Condition notFull = lock.newCondition();
三、构造函数
//默认的初始化大小
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();
}
}
1.offerFirst/offerLast 与 putFirst/putLast区别 队列满了的情况一个前者return false,后者调用notFull.await()
//在首节点位置添加
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();
}
}
//获取首节点,将添加元素E的next指针指向首节点。再把元素E作为首节点。 如果尾节点是null,那么E也是尾节点。不是null的话将E的pre指针指向last节点
private boolean linkFirst(Node<E> node) {
// assert lock.isHeldByCurrentThread();
if (count >= capacity) //判断当先链表的数目大小
return false;
Node<E> f = first;
node.next = f;
first = node;
if (last == null)
last = node;
else
f.prev = node;
++count;
notEmpty.signal(); //唤醒notEmpty等待的线程
return true;
}
//添加至尾节点
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();
}
}
//将节点E作为尾节点,E.prev并指向原先的尾节点l。判断首节点为null,E也是首节点。不为null,l.next指向E
private boolean linkLast(Node<E> node) {
// assert lock.isHeldByCurrentThread();
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(); //唤醒notEmpty等待的线程
return true;
}
//移出首节点元素
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;
}
public E pollLast() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return unlinkLast();
} finally {
lock.unlock();
}
}
private E unlinkLast() {
// assert lock.isHeldByCurrentThread();
Node<E> l = last;
if (l == null)
return null;
Node<E> p = l.prev;
E item = l.item;
l.item = null;
l.prev = l; // help GC
last = p;
if (p == null)
first = null;
else
p.next = null;
--count;
notFull.signal();
return item;
}