1. 程式人生 > >ArrayBlockingQueue詳解 - 多執行緒安全性進階

ArrayBlockingQueue詳解 - 多執行緒安全性進階

1.介紹

ArrayBlockingQueue是一個阻塞式的佇列,繼承自AbstractBlockingQueue,間接的實現了Queue介面和Collection介面。底層以陣列的形式儲存資料(實際上可看作一個迴圈陣列)。常用的操作包括 add ,offer,put,remove,poll,take,peek。

前三者add offer put 是插入的操作。後面四個方法是取出的操作。他們之間的區別和關聯:

add: 內部實際上獲取的offer方法,當Queue已經滿了時,丟擲一個異常。不會阻塞。

offer:當Queue已經滿了時,返回false。不會阻塞。

put:當Queue已經滿了時,會進入等待,只要不被中斷,就會插入資料到佇列中。會阻塞,可以響應中斷。

取出方法中 remove和add相互對應。也就是說,呼叫remove方法時,假如對列為空,則丟擲一場。另外的,poll與offer相互對應。take和put相互對應。peek方法比較特殊,前三個取出的方法,都會將元素從Queue的頭部溢位,但是peek不會,實際上只是,獲取佇列頭的元素。peek方法也不會阻塞。當佇列為空時,直接返回Null。

2.對比LinkedBlockingQueue

LinkedBlockingQueue也是一個阻塞式的佇列,與ArrayBlockingQueue的區別是什麼呢?

LinkedBlockingQueue儲存元素的是一個連結串列。其內部有一個Node的內部類,其中有一個成員變數 Node next。就這樣形成了一個連結串列的結構,要獲取下一個元素,只要呼叫next就可以了。而ArrayBlockingQueue則是一個數組。

LinkedBlockingQueue內部讀寫(插入獲取)各有一個鎖,而ArrayBlockingQueue則讀寫共享一個鎖。

3.選擇LinkedBlockingQueue還是ArrayBlockingQueue

個人感覺大多數場景適合使用LinkedBlockingQueue。在JDK原始碼當中有說明,LinkedBlockingQueue比ArrayBlockingQueue有更高的吞吐量,但是效能表現更難預測(也就是說相比ArrayBlockingQueue效能表現不穩定,但是也很穩定了)。

為什麼會有吞吐量的區別,個人以為可能是ArrayBlockingQueue兩個鎖的緣故,在大量併發的情況下,插入和讀取都很多時,就會造成一點的時間浪費。

還有一點,應為LinkedBlockingQueue建立時,預設會直接建立一個Integer.MAX_VALUE的陣列,當插入少,讀取多時,就會造成很大的空間浪費。而LinkedBlockingQueue實際上實在等需要的時候才會建立一個Node節點。