1. 程式人生 > >自己總結 :併發佇列ConcurrentLinkedQueue、阻塞佇列AraayBlockingQueue、阻塞佇列LinkedBlockingQueue 區別 和 使用場景總結

自己總結 :併發佇列ConcurrentLinkedQueue、阻塞佇列AraayBlockingQueue、阻塞佇列LinkedBlockingQueue 區別 和 使用場景總結

三者區別與聯絡: 聯絡,三者 都是執行緒安全的。區別,就是 併發  和 阻塞,前者為併發佇列,因為採用cas演算法,所以能夠高併發的處理;後2者採用鎖機制,所以是阻塞的。注意點就是前者由於採用cas演算法,雖然能高併發,但cas的特點造成操作的危險性,怎麼危險性可以去查一下cas演算法(但一些多消費性的佇列還是用的它,原因看下邊使用場景中的說明) 後2者區別:聯絡,第2和第3都是阻塞佇列,都是採用鎖,都有阻塞容器Condition,通過Condition阻塞容量為空時的取操作和容量滿時的寫操作第。區別,第2就一個整鎖,第3是2個鎖,所以第2第3的鎖機制不一樣,第3比第2吞吐量 大,併發效能也比第2高。
後2者的具體資訊:   LinkedBlockingQueue是BlockingQueue的一種使用Link List的實現,它對頭和尾(取和新增操作)採用兩把不同的鎖,相對於ArrayBlockingQueue提高了吞吐量。它也是一種阻塞型的容器,適合於實現“消費者生產者”模式。

ArrayBlockingQueue是對BlockingQueue的一個數組實現,它使用一把全域性的鎖並行對queue的讀寫操作,同時使用兩個Condition阻塞容量為空時的取操作和容量滿時的寫操作。

 正因為LinkedBlockingQueue使用兩個獨立的鎖控制資料同步,所以可以使存取兩種操作並行執行,從而提高併發效率。而ArrayBlockingQueue使用一把鎖,造成在存取兩種操作爭搶一把鎖,而使得效能相對低下。LinkedBlockingQueue可以不設定佇列容量,預設為Integer.MAX_VALUE.其容易造成記憶體溢位,一般要設定其值。

使用場景總結: 適用阻塞佇列的好處:多執行緒操作共同的佇列時不需要額外的同步,另外就是佇列會自動平衡負載,即那邊(生產與消費兩邊)處理快了就會被阻塞掉,從而減少兩邊的處理速度差距,自動平衡負載這個特性就造成它能被用於多生產者佇列,因為你生成多了(佇列滿了)你就要阻塞等著,直到消費者消費使佇列不滿你才可以繼續生產。 當許多執行緒共享訪問一個公共 collection 時,ConcurrentLinkedQueue 是一個恰當的選擇。 LinkedBlockingQueue 多用於任務佇列(單執行緒釋出任務,任務滿了就停止等待阻塞,當任務被完成消費少了又開始負載 釋出任務) ConcurrentLinkedQueue  多用於訊息佇列(多個執行緒傳送訊息,先隨便發來,不計併發的-cas特點) 多個生產者,對於LBQ效能還算可以接受;但是多個消費者就不行了mainLoop需要一個timeout的機制,否則空轉,cpu會飆升的。LBQ正好提供了timeout的介面,更方便使用 如果CLQ,那麼我需要收到處理sleep 單生產者,單消費者  用 LinkedBlockingqueue   多生產者,單消費者   用 LinkedBlockingqueue   單生產者 ,多消費者   用 ConcurrentLinkedQueue 多生產者 ,多消費者   用 ConcurrentLinkedQueue 對上邊總結:
如訊息佇列,好多client發來訊息,根據client傳送先後放入佇列中,先發送的就先放進來,然後由於佇列是先進先出,是一個一個出來的,所以不涉及到執行緒安全問題,所以用LinkedBlockingqueue  佇列。比如還拿上邊訊息佇列那個例子,由於佇列是一個一個出來的,出來一個訊息協議體就由執行緒池分配一個執行緒去處理這個訊息體,這個訊息體對於執行緒池來說談不上共享不共享的問題,即不會多個執行緒去搶同一個訊息體去執行,所以就不需要用執行緒安全的佇列結構了;那假如一種情況,佇列裡仍然是一個一個的出來,但是出來的這個元素是 執行緒池共享的,即大家執行緒都需要用到這個從佇列裡出來的這個元素,也就是多消費者消費同一個東西這種情況,所以就要用執行緒安全的隊列了,即ConcurrentLinkedQueue