????ConcurrentLinkedQueue
???????????????????????????????????????????????????????????
????????ConcurrentLinkedQueue??
????1???????????offer
????2???????????????offer??
????· ??????offer
????· ???????offer?????????poll
????  · offer??poll??
????  · poll??offer??
????offer
public boolean offer(E e) {
checkNotNull(e);
// ??????node
final Node<E> newNode = new Node<E>(e);
// ?????????for??г??????????????ж??????????????node???????
// ?????p??t???????tail
// ?????????????p????????????t???tail
for (Node<E> t = tail?? p = t;;) {
// q?????p???????
Node<E> q = p.next;
if (q == null) {
// p is last node
// ???q?null???p????????????????????
// ?????????????????????????p??????
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".
// node??????????tail?????????????????????????????????tail
if (p != t) // hop two nodes at a time
// ???????????tail???????????????????node??????????p.next??????null?ж???
casTail(t?? newNode);  // Failure is OK.
return true;
}
// Lost CAS race to another thread; re-read next
}
else if (p == q)
// ???q??p.next??????????????????offer???????poll????offer?????????p??poll????????poll?????е?updateHead??????head??????q??????p.next????????????p.next == p
// ??????????tail??head????棬???????????p
// ???tail????????p???tail??????????tail?????????head???
// ???tail??и??????p???head
// 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.
// tail????????????????p??????????
p = (p != t && t != (t = tail)) ? t : q;
}
}
????poll
public E poll() {
// ???????p???????????????head??????
restartFromHead:
for (;;) {
for (Node<E> h = head?? p = h?? q;;) {
E item = p.item;
if (item != null && p.casItem(item?? null)) {
// Successful CAS is the linearization point
// for item to be removed from this queue.
if (p != h) // hop two nodes at a time
updateHead(h?? ((q = p.next) != null) ? q : p);
return item;
}
else if ((q = p.next) == null) {
// ???????
updateHead(h?? p);
return null;
}
else if (p == q)
// ??????????poll??????????????????????p??????????——??p.next = p??p??????????????????????????
continue restartFromHead;
else
p = q;
}
}
}
final void updateHead(Node<E> h?? Node<E> p) {
if (h != p && casHead(h?? p))
h.lazySetNext(h);
}