Java中常用七個阻塞佇列的總結

kaizi1992發表於2020-05-04

Java佇列總結

通過前面文章的學習,我們對Java中常用佇列做了介紹。本文,我們們來對佇列做個總結吧。

首先,我們介紹了現實生活中的實際場景(排隊買票等),來告訴我們為什麼需要使用佇列。

佇列是一種先進先出(FIFO)的抽象資料結構,在Java中,佇列使用了兩種資料型別來實現的,分別是:陣列和連結串列這兩種資料結構。

本文主要內容:回顧Java中常用的七個阻塞佇列進行總結及阻塞佇列中四組AP並進行總結。

本文來源:本文是由凱哥Java(kaigejava)原創釋出。

接著,我們介紹了佇列的分類,可以分為兩類,即阻塞佇列和非阻塞佇列。

常用的三個非阻塞佇列:LinkedList、PriorityQueue和ConcurrentLinkedQueue.

(PS:凱哥沒有做介紹,在以後的文章中,凱哥將對ConcurrentLinkedQueue進行介紹)

然後我們介紹Java中常用的七個阻塞佇列。他們之間類圖關係:

 

我們可以看到,佇列是Collection的子類。也即和arrayList類似的。

接著我們就對七個阻塞佇列做了詳細的介紹。

阻塞佇列的七個子類

ArrayBlockingQueue(下文簡稱:ABQueue)、LinkedBlockingQueue(下文簡稱:LBQueue)、PriorityBlockingQueue(下文簡稱:PBQueue)、DelayQueue(下文簡稱:DQueue)、SynchronouseQueue(下文簡稱:SyncQueue)、LinkedTrnsferQueue(下文簡稱:LTQueue)、LinkedBlockingDeque(下文簡稱:LBDeque)這個七個。

 

來分別說說每個佇列的特點:

ABQueue:

底層使用的是陣列結構。因為陣列需要初始化大小,所以其構造器需要輸入佇列的大小。

是有界的阻塞安全佇列(思考:為什麼說是有界的?是怎麼保證執行緒安全的?),預設是不保證執行緒的公平性(思考:為什麼預設不能保證執行緒公平?如何保證執行緒安全?),不允許向佇列中插入null元素。

LBQueue:

“有界”的阻塞安全佇列,其底層使用的是連結串列的資料結構。所謂的“有界”是因為,預設佇列的大小是Integer.MAX_VALUE。這個數值等於21億+。因為這個資料太大了,也可以理解為無界的。不建議使用預設值,最好在初始化的時候,指定佇列的大小。

PBQueue:

是一個支援優先順序的無界佇列。支援優先順序是因為使用了comparator這個介面。預設採用字典升序排序策略的。如果不想使用預設的,在初始化的時候,還可以自定義比較器的。

以上三個佇列相關更詳細的介紹,歡迎回看《Java中常用的七個阻塞佇列介紹第一篇》。在這篇文章中,凱哥對這三個佇列做了詳細的介紹以及程式碼演示。

DQueue:

是一個支援優先順序的無界阻塞佇列。支援優先順序是應該底層使用的是PriorityQueue佇列來實現的。而PriorityQueue佇列在新增元素的時候使用了siftUpComparable方法。這個對了的一個特點:支援延時獲取。所以,這個佇列可以運用在快取系統的設計中。當從佇列中獲取到資料,說明延時時間到了。

關於DQueue更多詳細的介紹,歡迎回看:《Java中常用的七個阻塞佇列第二篇DelayQueue原始碼介紹》。在這篇文章中,凱哥做了詳細的介紹,同時使用程式碼模擬了快取資料到期操作。

SyncQueue:

是一個無儲存空間的阻塞同步佇列。不儲存元素的原因是因為,一個put操作必須等待一個take操作與之對應才可以。否則就不能繼續新增元素了。預設使用非公平的。在效能上SyncQueue佇列的吞吐量比LBqueu和ABQueue的效能高。

LTQueue:是由連結串列組成的無界佇列。比其他佇列多了兩個方法:tryTransfer、transfer

LBDeque:連結串列組成的雙端佇列。這個佇列在以後凱哥講For/Join框架的時候,還會說到。

七個阻塞佇列的小總結:

 

接著,我們講解了佇列中常用的四組API。

阻塞佇列四組API

會拋異常的:新增元素使用add(e),刪除元素使用remove,檢查隊首元素使用的element.

當佇列滿的時候,在向佇列中新增元素會丟擲異常;當佇列為空的時候在從佇列中刪除或者是獲取隊首元素都會丟擲異常;

帶有返回值的:新增元素:offer(e),刪除元素:poll(),檢查隊首元素:peek().

當佇列滿的時候,再呼叫offer(e)向佇列中新增元素會返回false而不是丟擲異常

當佇列為空的時候,呼叫take()或者是peek()方法返回null而不是丟擲異常

阻塞一直等待的:新增元素:put(e),刪除元素:take()

當佇列滿的時候,再向佇列中新增元素,佇列會進入阻塞狀態,直到元素新增成功為止。

當佇列為空的時候,再從佇列刪除元素,佇列會阻塞,直到能夠刪除元素為止。

帶有超時時間的阻塞:新增元素:offer(e,time,unit),刪除元素:poll(time,unit)

當佇列滿的時候,呼叫offer(e,time,unit)會進入阻塞等待中,當過來超時時間,退出等待

當佇列為空的時候,呼叫poll(time,unit)方法會進入等待狀態,當到了超時時間,會退出等待。

四組API總結:

 

關於四組API更詳細的介紹歡迎學習:《Java阻塞佇列的四組API》。在這篇文章中凱哥做了詳細的介紹。用人的一生四個階段來比擬這四組API。

到此,我們已經把Java中佇列介紹完畢。接下來,凱哥將帶著大家一起學習執行緒池。歡迎大家繼續學習。

相關文章