LinkedBlockingDeque是双端阻塞队列,它跟LinkedBlockingQueue的区别在于它可以做到后进先出,也就是实现栈的功能,本篇文章我们主要来看看它是如何实现后进先出的。
一、基本代码结构
从以下代码结构中可以看到,它跟LinkedBlockingQueue没什么差别,可以猜测它也是用重入锁控制并发访问。另外有两个等待队列用来阻塞队列满了或者空了的情况。
public class LinkedBlockingDeque<E>
extends AbstractQueue<E>
implements BlockingDeque<E>, java.io.Serializable {
/** Doubly-linked list node class */
static final class Node<E> {
E item;
Node<E> prev;
Node<E> next;
Node(E x) {
item = x;
}
}
transient Node<E> first;
transient Node<E> last;
/** Number of items in the deque */
private transient int count;
/** Maximum number of items in the deque */
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();
public LinkedBlockingDeque() {
this(Integer.MAX_VALUE);
}
public LinkedBlockingDeque(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
}
}
二、后进先出的实现
- 入队列是从队列头部插入,而不是尾部,调用的方法是push
public void push(E e) {
addFirst(e);
}
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();
}
}
- 出队列方法没什么差别,都是从头部取出节点
public E pop() {
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();
}
}
三、总结
- LinkedBlockingDeque是双端阻塞队列,内部是链表的结构,节点即可以先进先出,也可以后进先出。
- LinkedBlockingDeque也是用重入锁控制并发。
本文深入解析了Java并发包中的LinkedBlockingDeque,一种双端阻塞队列,它通过重入锁控制并发,能够实现先进先出和后进先出两种模式。文章详细介绍了其内部结构、实现原理及操作方法。
3406

被折叠的 条评论
为什么被折叠?



