天天看點

#yyds幹貨盤點#ConcurrentLinkedQueue

ConcurrentLinkedQueue

ConcurrentLinkedQueue是一個基于連結節點的無界線程安全隊列,它采用先進先出的規

則對節點進行排序,當我們添加一個元素的時候,它會添加到隊列的尾部;當我們擷取一個元

素時,它會傳回隊列頭部的元素。

ConcurrentLinkedQueue由head節點和tail節點組成,每個節點(Node)由節點元素(item)和

指向下一個節點(next)的引用組成,節點與節點之間就是通過這個next關聯起來,進而組成一

張連結清單結構的隊列。預設情況下head節點存儲的元素為空,tail節點等于head節點。

入隊列

public boolean offer(E e) {
    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;
    }
}
           

出隊列

public E poll() {
    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)
                continue restartFromHead;
            else
                p = q;
        }
    }
}