
本文首发于一世流云专栏:
https://segmentfault.com/blog...
一、引言
在开始讲ConcurrentLinkedDeque
之前,我们先来了解下Deque这种数据结构,我们知道Queue是一种具有FIFO特点的数据结构,元素只能在队首进行“入队”操作,在队尾进行“出队”操作。
而Deque(double-ended queue)是一种双端队列,也就是说可以在任意一端进行“入队”,也可以在任意一端进行“出队”:

Deque的数据结构示意图如下:

我们再来看下JDK中Queue和Deque这两种数据结构的接口定义,看看Deque和Queue相比有哪些增强:
Queue接口定义
Queue的接口非常简单,一共只有三种类型的操作:入队、出队、读取。

上述方法,可以划分如下:
操作类型 |
抛出异常 |
返回特殊值 |
入队 |
add(e) |
offer(e) |
出队 |
remove() |
poll() |
读取 |
element() |
peek() |
每种操作类型,都给出了两种方法,区别就是其中一种操作在队列的状态不满足某些要求时,会抛出异常;另一种,则直接返回特殊值(如null)。
Deque接口定义
Queue接口的所有方法Deque都具备,只不过队首/队尾都可以进行“出队”和“入队”操作:
操作类型 |
抛出异常 |
返回特殊值 |
队首入队 |
addFirst(e) |
offerFirst(e) |
队首出队 |
removeFirst() |
pollFirst() |
队首读取 |
getFirst() |
peekFirst() |
队尾入队 |
addLast(e) |
offerLast(e) |
队尾出队 |
removeLast() |
pollLast() |
队尾读取 |
getLast() |
peekLast() |
除此之外,Deque还可以当作“栈”来使用,我们知道“栈”是一种具有“LIFO”特点的数据结构(关于栈,可以参考我的这篇博文:栈),Deque提供了push
、pop
、peek
这三个栈方法,一般实现这三个方法时,可以利用已有方法,即有如下映射关系:
栈方法 |
Deque方法 |
push |
addFirst(e) |
pop |
removeFirst() |
peek |
peekFirst() |
关于Deque接口的更多细节,读者可以参考Oracle的官方文档:https://docs.oracle.com/javas...
二、ConcurrentLinkedDeque简介
ConcurrentLinkedDeque
是JDK1.7时,J.U.C包引入的一个集合工具类。在JDK1.7之前,除了Stack类外,并没有其它适合并发环境的“栈”数据结构。ConcurrentLinkedDeque作为双端队列,可以当作“栈”来使用,并且高效地支持并发环境。
ConcurrentLinkedDeque和ConcurrentLinkedQueue一样,采用了无锁算法,底层基于自旋+CAS的方式实现。

三、ConcurrentLinkedDeque原理
队列结构
我们先来看下ConcurrentLinkedDeque的内部结构:
public class ConcurrentLinkedDeque extends AbstractCollection
implements Deque, java.io.Serializable {
/**
* 头指针
*/
private transient volatile Node head;
/**
* 尾指针
*/
private transient volatile Node tail;
private static final Node