1、构造函数
public ConcurrentLinkedQueue() {
head = tail = new Node<E>(null);
}
点击new Node(null)进入如下代码
Node(E item) {
UNSAFE.putObject(this, itemOffset, item);
}
这里的itemOffset是item这个属性相对于Node对象地址的偏移量。
这个构造函数其实就是创建一个值为null的节点,并让head和tail指向该节点
这两个指针都是volatile的
private transient volatile Node<E> head;
private transient volatile Node<E> tail;
一张图总结:
注意:
1、Node类中只有next指针,说明这个队列是单项链表
2、offer方法
public boolean offer(E e) {
//值不能为null
checkNotNull(e);
final Node<E> newNode = new Node<E>(e);
for (Node<E> t = tail, p = t;;) {
Node<E> q = p.next;
if (q == null) {
// p is last node
if (p.casNext(null, newNode)) {
// Successful CAS is the linearization point
// for e to become an element of this queue,
// and for newNode to become "live".
if (p != t) // hop two nodes at a time
casTail(t, newNode); // Failure is OK.
return true;
}
// Lost CAS race to another thread; re-read next
}
else if (p == q)
// We have fallen off list. If tail is unchanged, it
// will also be off-list, in which case we need to
// jump to head, from which all live nodes are always
// reachable. Else the new tail is a better bet.
p = (t != (t = tail)) ? t : head;
else
// Check for tail updates after two hops.
p = (p != t && t != (t = tail)) ? t : q;
}
}
3、添加第一个元素
以offer(“张三”)为例
1) 执行到如下代码处
final Node<E> newNode = new Node<E>(e);
2)
Node<E> q = p.next;
3)下面这行代码的意思是,如果p节点的next指针指向null,则将其重新指向newNode
p.casNext(null, newNode)
点击casNext进入如下代码
boolean casNext(Node<E> cmp, Node<E> val) {
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
注意:这里是通过CAS操作把新节点添加到链表中,同一时间只有一个线程可以执行成功。
4、添加第二个元素
以offer(“李四”)为例
1)
final Node<E> newNode = new Node<E>(e);
2)
Node<E> q = p.next;
3)下面这个代码是将p指向了q指针
else
// Check for tail updates after two hops.
p = (p != t && t != (t = tail)) ? t : q;
第一轮循环结束,进入第二轮循环
4)
Node<E> q = p.next;
5)
p.casNext(null, newNode)
6)
if (p != t)
casTail(t, newNode);
5、添加第三个元素
以offer(“王五”)为例
1)
final Node<E> newNode = new Node<E>(e);
2)循环条件初始化
for (Node<E> t = tail, p = t;;)
3)
Node<E> q = p.next;
4)
p.casNext(null, newNode)