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。rem

2.對比LinkedBlockingQueue源碼

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

LinkedBlockingQueue保存元素的是一個鏈表。其內部有一個Node的內部類,其中有一個成員變量 Node next。就這樣造成了一個鏈表的結構,要獲取下一個元素,只要調用next就能夠了。而ArrayBlockingQueue則是一個數組。變量

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

3.選擇LinkedBlockingQueue仍是ArrayBlockingQueue

我的感受大多數場景適合使用LinkedBlockingQueue。在JDK源碼當中有說明,LinkedBlockingQueue比ArrayBlockingQueue有更高的吞吐量,可是性能表現更難預測(也就是說相比ArrayBlockingQueue性能表現不穩定,可是也很穩定了)。

爲何會有吞吐量的區別,我的覺得多是ArrayBlockingQueue兩個鎖的緣故,在大量併發的狀況下,插入和讀取都不少時,就會形成一點的時間浪費。

還有一點,應爲LinkedBlockingQueue建立時,默認會直接建立一個Integer.MAX_VALUE的數組,當插入少,讀取多時,就會形成很大的空間浪費。而LinkedBlockingQueue實際上實在等須要的時候纔會建立一個Node節點。  

相關文章
相關標籤/搜索