阻塞隊列 BlockingQueued & 條件隊列和同步隊列


一、BlockingQueued

BlockingQueued 隊列使用 ReentrantLock 和 Condition(AQS實現)來實現的。Condition 只能用於獨占模式。

條件隊列中的節點永遠不會被喚醒,一直阻塞者;要想喚醒,則需要把該節點放到CLH隊列中,放入到CLH隊列中才有機會去競爭、喚醒;

條件隊列是單向鏈表,CLH隊列為雙向鏈表。

首先看一下 BlockingQueued 的源碼:

public interface BlockingQueue<E> extends Queue<E> {

    //將給定元素設置到隊列中,如果設置成功返回true, 否則返回false。如果是往限定了長度的隊列中設置值,推薦使用offer()方法。
    boolean add(E e);

    //將給定的元素設置到隊列中,如果設置成功返回true, 否則返回false. e的值不能為空,否則拋出空指針異常。
    boolean offer(E e);

    //將元素設置到隊列中,如果隊列中沒有多余的空間,該方法會一直阻塞,直到隊列中有多余的空間。
    void put(E e) throws InterruptedException;

    //將給定元素在給定的時間內設置到隊列中,如果設置成功返回true, 否則返回false.
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;

    //從隊列中獲取值,如果隊列中沒有值,線程會一直阻塞,直到隊列中有值,並且該方法取得了該值。
    E take() throws InterruptedException;

    //在給定的時間里,從隊列中獲取值,時間到了直接調用普通的poll方法,為null則直接返回null。
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;

    //獲取隊列中剩余的空間。
    int remainingCapacity();

    //從隊列中移除指定的值。
    boolean remove(Object o);

    //判斷隊列中是否擁有該值。
    public boolean contains(Object o);

    //將隊列中值,全部移除,並發設置到給定的集合中。
    int drainTo(Collection<? super E> c);

    //指定最多數量限制將隊列中值,全部移除,並發設置到給定的集合中。
    int drainTo(Collection<? super E> c, int maxElements);
}

 

 1. ArrayBlockingQueued

由數組支持的有界隊列;容量大小在創建ArrayBlockingQueue對象時已定義好。默認情況下不保證線程公平的訪問隊列。

 分析源碼

2. LinkedBlockingQueue

由鏈接節點支持的可選有界隊列;此隊列的默認和最大長度為 Integer.MAX_VALUE。

3. PriorityBlockingQueue

由優先級堆支持的無界優先級隊列;

  默認情況下元素采取自然順序升序排列。也可以自定義類實現compareTo()方法來指定元素排序規則,或者初始化PriorityBlockingQueue時,指定構造參數Comparator來對元素進行排序。需要注意的是不能保證同優先級元素的順序。

4. DelayQueue 

  由優先級隊列支持的、基於時間的調度隊列,內部基於無界隊列PriorityQueue實現,而無界隊列基於數組的擴容實現。

  隊列中的元素必須實現Delayed接口,在創建元素時可以指定多久才能從隊列中獲取當前元素。只有在延遲期滿時才能從隊列中提取元素。

5. SynchronousQueue

  SynchronousQueue是一個不存儲元素的阻塞隊列。每一個put操作必須等待一個take操作,否則不能繼續添加元素。

  它支持公平訪問隊列。默認情況下線程采用非公平性策略訪問隊列。使用以下構造方法可以創建公平性訪問的SynchronousQueue,如果設置為true,則等待的線程會采用先進先出的順序訪問隊列。

6.LinkedTransferQueue

LinkedTransferQueue是一個由鏈表結構組成的無界阻塞TransferQueue隊列。相對於其他阻塞隊列,LinkedTransferQueue多了tryTransfer和transfer方法。

(1)transfer方法

  如果當前有消費者正在等待接收元素(消費者使用take()方法或帶時間限制的poll()方法時),transfer方法可以把生產者傳入的元素立刻transfer(傳輸)給消費者。如果沒有消費者在等待接收元素,transfer方法會將元素存放在隊列的tail節點,並等到該元素被消費者消費了才返回。

(2)tryTransfer方法

  tryTransfer方法是用來試探生產者傳入的元素是否能直接傳給消費者。如果沒有消費者等待接收元素,則返回false。和transfer方法的區別是tryTransfer方法無論消費者是否接收,方法立即返回,而transfer方法是必須等到消費者消費了才返回。

7.LinkedBlockingDeque

  LinkedBlockingDeque是一個由鏈表結構組成的雙向阻塞隊列。所謂雙向隊列指的是可以從隊列的兩端插入和移出元素。雙向隊列因為多了一個操作隊列的入口,在多線程同時入隊時,也就減少了一半的競爭。相比其他的阻塞隊列,LinkedBlockingDeque多了addFirst、addLast、offerFirst、offerLast、peekFirst和peekLast等方法,以First單詞結尾的方法,表示插入、獲取(peek)或移除雙端隊列的第一個元素。以Last單詞結尾的方法,表示插入、獲取或移除雙端隊列的最后一個元素。另外,插入方法add等同於addLast,移除方法remove等效於removeFirst。但是take方法卻等同於takeFirst,不知道是不是JDK的bug,使用時還是用帶有First和Last后綴的方法更清楚。

 

參考鏈接:https://www.cnblogs.com/WangHaiMing/p/8798709.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM