文章目錄
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:基於鏈表組成的無界傳輸阻塞隊列。