简介
ConcurrentLinkedDeque是线程安全的非阻塞队列,内部结构跟LinkedBlockingQueue一样使用双向链表,最大的区别就是LinkedBlockingDeque使用CSA原则操作,没有用lock。使用它的时候一样需要注意,头节点和尾节点不保证一定是头和尾。
ConcurrentLinkedDeque类
public class ConcurrentLinkedDeque<E>
extends AbstractCollection<E>
implements Deque<E>, java.io.Serializable
继承AbstractCollection,实现Deque接口
重要内部类Node
static final class Node<E>
Node 属性
// 前一个节点
volatile Node<E> prev;
// 当前节点元素
volatile E item;
// 后一个节点
volatile Node<E> next;
// 操作内存不安全类
private static final sun.misc.Unsafe UNSAFE;
// 前一个节点偏移量
private static final long prevOffset;
// 当前元素偏移量
private static final long itemOffset;
// 下一个节点偏移量
private static final long nextOffset;
Node 初始化内存操作
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> k = Node.class;
prevOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField("prev"));
itemOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField("item"));
nextOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField("next"));
} catch (Exception e) {
throw new Error(e);
}
}
Node 构造函数
Node() {
}
Node(E item) {
UNSAFE.putObject(this, itemOffset, item);
}
Node 方法
boolean casItem(E cmp, E val) {
return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
}
void lazySetNext(Node<E> val) {
UNSAFE.putOrderedObject(this, nextOffset, val);
}
boolean casNext(Node<E> cmp, Node<E> val) {
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
void lazySetPrev(Node<E> val) {
UNSAFE.putOrderedObject(this, prevOffset, val);
}
boolean casPrev(Node<E> cmp, Node<E> val) {
return UNSAFE.compareAndSwapObject(this, prevOffset, cmp, val);
}
搞懂Unsafe,看Node方法还是很简单的。
ConcurrentLinkedDeque 属性
// 头节点
private transient volatile Node<E> head;
// 尾节点
private transient volatile Node<E> tail;
// 终止节点
private static final Node<Object> PREV_TERMINATOR, NEXT_TERMINATOR;
// 阈值
private static final int HOPS = 2;
// 内存操作不安全类
private static final sun.misc.Unsafe UNSAFE;
// 头节点偏移量
private static final long headOffset;
// 尾节点偏移量
private static final long tailOffset;
ConcurrentLinkedDeque 构造函数
public ConcurrentLinkedDeque() {
// 初始化一个空元素节点
head = tail = new Node<E>(null);
}
public ConcurrentLinkedDeque(Collection<? extends E> c) {
Node<E> h = null, t = null;
// 便利线性集合
for (E e : c) {
// 检查元素是否为空
checkNotNull(e);
// 构建节点
Node<E> newNode = new Node<E>(e);
// 头节点为空设置头节点,不为空设置下级节点
if (h == null)
h = t = newNode;
else {
t.lazySetNext(newNode);
newNode.lazySetPrev(t);
t = newNode;
}
}
// 设计尾节点
initHeadTail(h, t);
}
ConcurrentLinkedDeque 基础方法
更新头节点
private final void updateHead() {
Node<E> h, p, q;
restartFromHead:
// 头节点元素为空,上一个节点不为空
while ((h = head).item == null && (p = h.prev) != null) {
for (;;) {
// 头节点上一个节点为空或上上节点为空
if ((q = p.prev) == null ||
(q = (p = q).prev) == null) {
// 跟新p为头节点
if (casHead(h, p))
return;
else
continue restartFromHead;
}
// 头节点改变了重新设置
else if (h != head)
continue restartFromHead;
else
p = q;
}
}
}
更新尾节点
private final void updateTail() {
Node<E> t, p, q;
restartFromTail:
// 尾节点为空或尾节点下一个节点为空
while ((t = tail).item == null && (p = t.next) != null) {
for (;;) {
// 尾节点下一个为空,或下下一个为空
if ((q = p.next) == null ||
(q = (p = q).next) == null) {
// 设置尾节点
if (casTail(t, p))
return;
else
continue restartFromTail;
}
// 尾节点已经改变重新设置
else if (t != tail)
continue restartFromTail;
else
p = q;
}
}
}
获取头节点
Node<E> first() {
restartFromHead:
for (;;)
// 从头节点开始遍历
for (Node<E> h = head, p = h, q;;) {
// 前面还有节点
if ((q = p.prev) != null &&
(q = (p = q).prev) != null)
// p 前移
p = (h != (h = head)) ? h : q;
else if (p == h
// 修改头节点
|| casHead(h, p))
// 返回头节点
return p;
else
continue restartFromHead;
}
}
获取尾节点
Node<E> last() {
restartFromTail:
for (;;)
// 从尾节点开始遍历
for (Node<E> t = tail, p = t, q;;) {
// 尾节点后还有节点
if ((q = p.next) != null &&
(q = (p = q).next) != null)
// p 后移
p = (t != (t = tail)) ? t : q;
else if (p == t
// 更新尾节点
|| casTail(t, p))
return p;
else
continue restartFromTail;
}
}
ConcurrentLinkedDeque 添加
public boolean offerFirst(E e) {
// 调用linkFirst
linkFirst(e);
return true;
}
public boolean offerLast(E e) {
// 调用linkLast
linkLast(e);
return true;
}
委托linkFirst、linkLast方法
private void linkFirst(E e) {
// 检查是否为空
checkNotNull(e);
// 构建新节点
final Node<E> newNode = new Node<E>(e);
restartFromHead:
for (;;)
// 循环头节点
for (Node<E> h = head, p = h, q;;) {
// 上一个节点不为空并且上上一个节点不为空
if ((q = p.prev) != null &&
(q = (p = q).prev) != null)
// p 节点前移
p = (h != (h = head)) ? h : q;
else if (p.next == p) // 头节点移除会自己指向自己
continue restartFromHead;
else {
// 新节点下一个节点设置为p节点
newNode.lazySetNext(p);
// 设置p上级节点为新节点
if (p.casPrev(null, newNode)) {
// 后一个线程去更新头节点
if (p != h)
casHead(h, newNode);
return;
}
}
}
}
private void linkLast(E e) {
// 检查是否为空
checkNotNull(e);
// 构建新节点
final Node<E> newNode = new Node<E>(e);
restartFromTail:
for (;;)
// 循环尾节点
for (Node<E> t = tail, p = t, q;;) {
// 下一个节点不为空并且下下一个节点不为空
if ((q = p.next) != null &&
(q = (p = q).next) != null)
// 后移p节点
p = (t != (t = tail)) ? t : q;
else if (p.prev == p) // 尾节点移除会自己指向自己
continue restartFromTail;
else {
// 新节点上一个节点设置为p
newNode.lazySetPrev(p);
// 设置p的下级节点为新节点
if (p.casNext(null, newNode)) {
// 后一个线程去更新尾节点
if (p != t)
casTail(t, newNode);
return;
}
}
}
}
ConcurrentLinkedDeque 出队
头部出队
public E pollFirst() {
// 找头节点,然后遍历
for (Node<E> p = first(); p != null; p = succ(p)) {
// 获取元素
E item = p.item;
// 把当前头元素修改为null
if (item != null && p.casItem(item, null)) {
// 从链表中移除
unlink(p);
return item;
}
}
return null;
}
尾部出队
public E pollLast() {
// 找尾节点,然后开始遍历
for (Node<E> p = last(); p != null; p = pred(p)) {
// 获取元素
E item = p.item;
// 把当前头元素修改为null
if (item != null && p.casItem(item, null)) {
// 从链表中移除
unlink(p);
return item;
}
}
return null;
}
删除元素
void unlink(Node<E> x) {
// 获取当前节点上一个下一个节点
final Node<E> prev = x.prev;
final Node<E> next = x.next;
// 上一个节点为空,修改下一个节点为头节点
if (prev == null) {
unlinkFirst(x, next);
} else if (next == null) {
// 下一个节点为空,修改上一个节点为尾节点
unlinkLast(x, prev);
} else {// 能到这说明上下节点不为null
Node<E> activePred, activeSucc;
boolean isFirst, isLast;
int hops = 1;
// 往前遍历
for (Node<E> p = prev; ; ++hops) {
// x上一个节点元素不为空
// 说明x不是头节点
if (p.item != null) {
activePred = p;
isFirst = false;
break;
}
// x的上上一个节点
Node<E> q = p.prev;
// 上上一个节点为空
if (q == null) {
// 看一下p是不是已经变成活动节点了
if (p.next == p)
return;
activePred = p;
// 设置为头节点
isFirst = true;
break;
}
// 活动节点自引用
else if (p == q)
return;
else
// 前移
p = q;
}
// 找下一个节点
for (Node<E> p = next; ; ++hops) {
// x下一个节点元素不为空
// 说明x不是尾节点
if (p.item != null) {
activeSucc = p;
isLast = false;
break;
}
// 找下下一个节点
Node<E> q = p.next;
// 下下一个节点为空
if (q == null) {
// 看看是否是自引用了
if (p.prev == p)
return;
activeSucc = p;
// 设置为尾节点
isLast = true;
break;
}
// 自引用了
else if (p == q)
return;
else
// 后移
p = q;
}
// 小于阈值 并且是头节点或者是尾节点直接返回
if (hops < HOPS && (isFirst | isLast))
return;
// 是头节点或尾节点
if ((isFirst | isLast) &&
(activePred.next == activeSucc) &&
(activeSucc.prev == activePred) &&
(isFirst ? activePred.prev == null : activePred.item != null) &&
(isLast ? activeSucc.next == null : activeSucc.item != null)) {
// 修改头节点或尾节点
updateHead();
updateTail();
x.lazySetPrev(isFirst ? prevTerminator() : x);
x.lazySetNext(isLast ? nextTerminator() : x);
}
}
}
头部删除元素
private void unlinkFirst(Node<E> first, Node<E> next) {
for (Node<E> o = null, p = next, q;;) {
// next 的元素不为空或者next 下一个元素为空
if (p.item != null || (q = p.next) == null) {
// o不为空,所以第一次不能进来
if (o != null && p.prev != p && first.casNext(next, p)) {
skipDeletedPredecessors(p);
// 修改头节点和尾节点
if (first.prev == null &&
(p.next == null || p.item != null) &&
p.prev == first) {
updateHead();
updateTail();
o.lazySetNext(o);
o.lazySetPrev(prevTerminator());
}
}
return;
}
else if (p == q)
return;
else {
// 节点后移
o = p;
p = q;
}
}
}
尾部删除元素
private void unlinkLast(Node<E> last, Node<E> prev) {
for (Node<E> o = null, p = prev, q;;) {
// prev 元素不为空或者prev的前一个节点为空
if (p.item != null || (q = p.prev) == null) {
// o不为空,一样第一次不能进来
if (o != null && p.next != p && last.casPrev(prev, p)) {
skipDeletedSuccessors(p);
// 修改头和尾
if (last.next == null &&
(p.prev == null || p.item != null) &&
p.next == last) {
updateHead();
updateTail();
o.lazySetPrev(o);
o.lazySetNext(nextTerminator());
}
}
return;
}
else if (p == q)
return;
else {
// 节点前移
o = p;
p = q;
}
}
}
ConcurrentLinkedDeque 查询
public E peekFirst() {
// 从头部开始遍历
for (Node<E> p = first(); p != null; p = succ(p)) {
// 找到第一个节点元素返回
E item = p.item;
if (item != null)
return item;
}
return null;
}
public E peekLast() {
// 从尾部开始遍历
for (Node<E> p = last(); p != null; p = pred(p)) {
// 找到最后一个节点元素返回
E item = p.item;
if (item != null)
return item;
}
return null;
}