BlockingQueue(同步阻塞隊列)

1. Queue、Deque、BlockingQueue

  • Queue(隊列):用於保存一組元素,不過在存取元素的時候必須遵循先進先出原則。隊列是一種特殊的線性表,只能在表的前端(隊頭)進行刪除操作,在後端(隊尾)進行插入操作。隊列稱爲“先進先出”(FIFO)的線性表。
  • Deque(雙端隊列):兩端都可以進出的隊列。
  • BlockingQueue(同步阻塞隊列):阻塞隊列是一個支持兩個附加操作的隊列。這兩個附加的操作是:在隊列爲空時,獲取元素的線程會等待隊列變爲非空;當隊列滿時,存儲元素的線程會等待隊列可用。阻塞隊列常用於生產者和消費者的場景,生產者是往阻塞隊列中添加元素的線程,消費者是從隊列裏取出數據的線程。阻塞隊列就是生產者存放元素的容器,而消費者也只從容器裏取出元素。

2. BlockingQueue

BlockingQueue源碼中包含的方法如下:

package java.util.concurrent;

import java.util.Collection;
import java.util.Queue;

public interface BlockingQueue<E> extends Queue<E> {
    
    boolean add(E e);
    boolean offer(E e);
    void put(E e) throws InterruptedException;
    boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
    E take() throws InterruptedException;
    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);

}

BlockingQueue中常用的方法有如下5種:

  • boolean add(E e):表示把對象e添加到BlockingQueue中,如果能夠容納,則返回true,否則拋出異常;
  • boolean offer(E e):表示如果可能的話,將對象e加到BlockingQueue中,如果能夠容納,則返回true,否則拋出異常;
  • void put(E e):將對象e加入到BlockingQueue中,如果BlockingQueue沒有空間,則調用此方法的線程被阻斷,直到BlockingQueue裏面有空間時再繼續;
  • E take():取出BlockingQueue中排在首位的對象,若BlockingQueue爲空導致取不到對象,則阻斷當前線程進入等待狀態直到BlockingQueue中有新的對象被加入爲止;
  • E poll(long timeout, TimeUnit unit):取走BlockingQueue中排在首位的對象,若不能立即取出,則可以等待指定的時間,取不到時返回null。

注意:BlockingQueue不接受null元素。試圖add、put或offer一個null元素時,某些實現會拋出NullPointerException異常。null被用作指示poll操作失敗時的警戒值。

3. BlockingQueue的實現類(7種)

JDK中提供了7個實現了BlockingQueue的阻塞隊列,都位於java.util.concurrent包下:

  • ArrayBlockingQueue:基於數組的有界阻塞隊列;
  • LinkedBlockingQueue:基於鏈表的有界(可以通過構造函數指定隊列緩衝區容量)阻塞隊列;
  • PriorityBlockingQueue:一個支持優先級排序無界阻塞隊列(優先級的判斷通過構造函數傳入的Comparator對象決定),注意:PriorityBlockingQueue並不會阻塞數據生產者,而只會在沒有可消費的數據時,阻塞數據的消費者。因此,使用的時候設置不當會最終耗盡所有的可用堆內存空間。
  • DelayQueue:DelayQueue是一個支持延時獲取元素的使用優先級隊列的實現的無界阻塞隊列。隊列中的元素必須實現Delay接口和Comparable接口,也就是說DelayQueue中的元素必須有public int compareTo(To)long getDelay(TimeUnit unit)方法存在,在創建元素時可以指定多久才能從隊列中獲取當前元素。只有在延遲期滿時才能從隊列中提取元素。
  • SynchronousQueue:不存儲元素的阻塞隊列。每一個put操作必須等待一個take操作,否則不能繼續添加元素。
  • LinkedBlockingDeque:基於鏈表的雙向阻塞隊列。雙向隊列是指可以從隊列的兩端插入和移出元素。
  • LinkedTransferQueue:基於鏈表組成的無界傳輸阻塞隊列

3.1 ArrayBlockingQueue

3.2 LinkedBlockingQueue

3.3 PriorityBlockingQueue

3.4 DelayQueue

3.5 SynchronousQueue

3.6 LinkedBlockingDeque

3.7 LinkedTransferQueue

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章