1. 程式人生 > 其它 >前端基礎第二階段js基礎

前端基礎第二階段js基礎

繼承關係圖

/**
     * 節點類,用於儲存資料
     */
    static class Node<E> {
        E item;
        Node<E> next;

        Node(E x) { item = x; }
    }

    /**
     * 阻塞佇列的大小,預設為Integer.MAX_VALUE
     */
    private final int capacity;

    /**
     * 當前阻塞佇列中的元素個數
     */
    private final AtomicInteger count = new
AtomicInteger(); /** * 阻塞佇列的頭結點 */ transient Node<E> head; /** * 阻塞佇列的尾節點 */ private transient Node<E> last; /** * 獲取並移除元素時使用的鎖,如take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** * notEmpty條件物件,當佇列沒有資料時用於掛起執行刪除的執行緒
*/ private final Condition notEmpty = takeLock.newCondition(); /** * 新增元素時使用的鎖如 put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** * notFull條件物件,當佇列資料已滿時用於掛起執行新增的執行緒 */ private final Condition notFull = putLock.newCondition();

這裡如果不指定佇列的容量大小,也就是使用預設的Integer.MAX_VALUE,如果存在新增速度大於刪除速度時候,有可能會記憶體溢位,這點在使用前希望慎重考慮。

另外,LinkedBlockingQueue對每一個lock鎖都提供了一個Condition用來掛起和喚醒其他執行緒。

預設的建構函式和最後一個建構函式建立的佇列大小都為Integer.MAX_VALUE,只有第二個建構函式使用者可以指定佇列的大小。第二個建構函式最後初始化了last和head節點,讓它們都指向了一個元素為null的節點。

最後一個建構函式使用了putLock來進行加鎖,但是這裡並不是為了多執行緒的競爭而加鎖,只是為了放入的元素能立即對其他執行緒可見。

put方法來看,它總共做了以下情況的考慮:

佇列已滿,阻塞等待。
佇列未滿,建立一個node節點放入佇列中,如果放完以後佇列還有剩餘空間,繼續喚醒下一個新增執行緒進行新增。如果放之前佇列中沒有元素,放完以後要喚醒消費執行緒進行消費。

 連結串列演算法

private E dequeue() {
    // 獲取到head節點
    Node<E> h = head;
    // 獲取到head節點指向的下一個節點,也就是節點A
    Node<E> first = h.next;
    // 獲取到下下個節點,也就是節點B
    Node<E> next = first.next;
    // head的next指向下下個節點,也就是圖中的B節點
    h.next = next;
    // 得到節點A的值
    E x = first.item;
    first.item = null; // help GC
    first.next = first; // help GC
    return x;
}

https://blog.csdn.net/tonywu1992/article/details/83419448