2013-08-22 39 views
31
  1. 什麼情況下最好使用ArrayBlockingQueue以及何時使用LinkedBlockingQueue更好?
  2. 如果LinkedBlockingQueue默認容量等於MAX Integer,那麼使用它作爲具有默認容量的BlockingQueue是否真的有用?
+0

對於#1的點,我想這和ArrayList vs LinkedList的原因完全一樣;) – sp00m

+0

BlockingQueue不僅阻塞put()。當隊列爲空時,它也會阻塞take()。 –

+0

@ sp00m,但在插入或刪除之間沒有插入隊列。所以沒有像ArrayList和LinkedList那樣的性能問題 –

回答

17

ArrayBlockingQueue由大小在創建後永遠不會改變的數組支持。將容量設置爲Integer.MAX_VALUE將會產生空間成本高的大陣列。 ArrayBlockingQueue總是有界的。

LinkedBlockingQueue動態創建節點,直到達到capacity。這是默認的Integer.MAX_VALUE。使用這麼大的容量在太空中沒有額外的成本。 LinkedBlockingQueue是可選的有界。

12

ArrayBlockingQueue<E>LinkedBlockingQueue<E>BlockingQueue<E>接口的常用實現。

ArrayBlockingQueue得到arrayQueue的支持,命令爲FIFO。隊列頭是時間上最古老的元素,隊列的尾部是最年輕的元素。另一方面,ArrayBlockingQueue也是固定大小的有界緩衝區LinkedBlockingQueue是構建在鏈接節點之上的可選有界隊列。

可選的容量綁定構造函數參數用作防止過多隊列擴展的一種方式,因爲如果容量未指定,則等於Integer.MAX_VALUE

閱讀更多從here

基準:http://www.javacodegeeks.com/2010/09/java-best-practices-queue-battle-and.html

+0

我懷疑LinkedBlockingQueue會有更高的吞吐量。任何becnhmarks支持索賠? –

+1

@EskoLuontola:你可以在這裏找到一個基準: http://www.javacodegeeks.com/2010/09/java-best-practices-queue-battle-and.html –

+1

所以基於那個基準LinkedBlockingQueue更快產生消費者的場景,但在前兩個基準測試中,ArrayBlockingQueue稍快。不管怎麼說,Disruptor都會用這兩種方法來清理地板:https://code.google.com/p/disruptor/wiki/PerformanceResults –

5

添加到ArrayBlockingQueue一個元件被認爲是更快,因爲它意味着僅設置於背襯對象陣列的元素的引用,同時加入到的LinkedBlockingQueue的元件意味着創建節點和設置其item,prev和next字段。此外,當我們從LinkedBlockingQueue中移除一個元素時,被移除的Node變成垃圾,可能會影響應用程序的性能。

至於內存消耗即使在空時,ArrayBlockingQueue也始終保持一個具有全部容量的Object數組。另一方面,LinkedBlockingQueue中的一個元素是一個帶有3個對象字段的對象的節點。

+0

這是一個很好的解釋原因的答案,但是您提到ArrayBlockingQueue應該更快,我同意與你基於你提供的原因。但Javadocs稱這一點「鏈接隊列通常比基於陣列的隊列具有更高的吞吐量,但在大多數併發應用程序中性能不太可預測。」請參閱LinkedBlockingQueue.class – spiderman

+1

延遲和吞吐量是兩件不同的事情。ArrayBlockingQueue具有更好的延遲,因爲在數組中設置引用的速度更快,而LinkedBlockingQueue具有更好的吞吐量,因爲它對put和take使用2個差異鎖定,並且僅在邊緣條件下同步。 –

1

ArrayBlockingQueue

ArrayBlockingQueue是有界的,阻塞隊列在內部存儲元件的陣列。它是有限的意味着它不能存儲無限量的元素。它可以同時存儲的元素數量有一個上限。您在實例化時間設置上限,之後不能更改。

的LinkedBlockingQueue

的的LinkedBlockingQueue保持在一個聯結構(鏈接的節點)內部的元素。如果需要,該鏈接結構可以可選地具有上限。如果沒有指定上限,則使用Integer.MAX_VALUE作爲上限。

相似度

的ArrayBlockingQueue /的LinkedBlockingQueue內部存儲元件中FIFO(先入先出)次序。隊列的頭部是隊列中最長時間的元素,隊列的尾部是隊列中最短時間的元素。

差異

  • 的LinkedBlockingQueue具有putLock和takeLock用於插入和移除分別但ArrayBlockingQueue僅使用1鎖。
  • ArrayBlockingQueue使用單鎖雙條件算法,LinkedBlockingQueue是「雙鎖隊列」算法的變體,它有2個鎖2條件(takeLock,putLock)。

LinkedBlockingQueue實現正在使用兩個鎖定隊列算法。因此LinkedBlockingQueue的take和put可以同時工作,但ArrayBlockingQueue並非如此。在ArrayBlockingQueue中使用單個鎖的原因是,ArrayBlockingQueue必須避免覆蓋條目,以便它需要知道起始位置和結束位置。 LinkedBlockQueue不需要知道這一點,因爲它讓GC擔心清理隊列中的節點。