本篇文章是【Java集合系列】文章队列篇的第二篇,本系列将会逐个分析 Java 中的常用集合的特性及实现,然后对比不同场景下应该选择哪种集合使用。
List 系列
Queue系列
- ArrayDeque
- ConcurrentLinkedDeque
- LinkedBlockingDeque
ConcurrentLinkedDeque
ConcurrentLinkedDeque 是基于链表的无限双端队列,线程安全,不允许 null 元素。
ConcurrentLinkedDeque 内部通过 CAS 来实现线程同步,一般来说,如果需要使用线程安全的双端队列,那么推荐使用该类。
由于双端队列的特性,该类同样可以当做栈来使用,所以如果需要在并发环境下使用栈,也可以使用该类。
迭代器设计为弱一致性的(weakly consistent),此外还可以通过descendingIterator
方法获取一个通过相反方向遍历的迭代器。
虽然跟 LinkedList 一样都是双端队列的链表实现,但由于其并发特性,导致无法简单点的通过计数来确定队列的长度,所以size
方法将会以线性时间运行,并且如果在执行期间被其它线程修改可能返回不准确的结果。
对于批量操作,例如:addAll,removeAll,retainAll,containsAll,equals,toArray
来说,不能保证这些操作的原子性。
方法
ConcurrentLinkedDeque 作为队列(FIFO)使用时的方法:
队列方法 | 等效的双端队列方法 |
---|---|
add(e) | addLast(e) |
offer(e) | offerLast(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
ConcurrentLinkedDeque 作为堆栈(FILO)使用时的方法:
堆栈方法 | 等效的双端队列方法 |
---|---|
push(e) | addFirst(e) |
pop(e) | removeFirst(e) |
peek() | peekFirst() |
源码
因为 ConcurrentLinkedDeque 是基于链表的数据结构,我们先看看该类中使用的链表节点 Node 的相关代码。
Node
static final class Node<E> {
volatile Node<E> prev;
volatile E item;
volatile Node<E> next;
private static final sun.misc.Unsafe UNSAFE;
private static final long prevOffset;
private stat