並發隊列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。