版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第JAVA并發(fā)容器的一些易出錯(cuò)點(diǎn)你知道嗎目錄并發(fā)容器ListSetMapQueue單端阻塞隊(duì)列雙端阻塞隊(duì)列單端非阻塞隊(duì)列雙端非阻塞隊(duì)列有界與無(wú)界隊(duì)列總結(jié)
并發(fā)容器
與同步容器一樣,并發(fā)容器在總體上也可以分為四大類(lèi),分別為:List、Set、Map和Queue??傮w上如下圖所示。
接下來(lái),我們分別介紹下這些并發(fā)容器在使用時(shí)的注意事項(xiàng)和避免踩到的坑。
List
并發(fā)容器中的List相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,就一個(gè)CopyOnWriteArrayList。大家可以從字面的意思中就能夠體會(huì)到:CopyOnWrite,在寫(xiě)的時(shí)候進(jìn)行復(fù)制操作,也就是說(shuō)在進(jìn)行寫(xiě)操作時(shí),會(huì)將共享變量復(fù)制一份。那這樣做有什么好處呢?最大的好處就是:讀操作可以做到完全無(wú)鎖化。
在CopyOnWriteArrayList內(nèi)部維護(hù)了一個(gè)數(shù)組,成員變量array指向這個(gè)數(shù)組,其核心源代碼如下所示。
privatetransientvolatileObject[]array;
finalObject[]getArray(){
returnarray;
finalvoidsetArray(Object[]a){
array=a;
當(dāng)進(jìn)行操作時(shí),都是基于array指向的這個(gè)內(nèi)部數(shù)組進(jìn)行的。例如,我們使用Iterator迭代器遍歷這個(gè)數(shù)組時(shí),會(huì)按照下圖所示的方式進(jìn)行讀操作。
如果在遍歷CopyOnWriteArrayList時(shí)發(fā)生寫(xiě)操作,例如,向數(shù)組中增加一個(gè)元素時(shí),CopyOnWriteArrayList則會(huì)將內(nèi)部的數(shù)組復(fù)制一份出來(lái),然后會(huì)在新復(fù)制出來(lái)的數(shù)組上添加新的元素,添加完再將array指向新的數(shù)組,如下圖所示。
對(duì)于CopyOnWriteArrayList的其他寫(xiě)操作和添加元素的操作原理相同,這里就不再贅述了。
使用CopyOnWriteArrayList時(shí)需要注意的是:
CopyOnWriteArrayList只適合寫(xiě)操作比較少的場(chǎng)景,并且能夠容忍讀寫(xiě)操作在短時(shí)間內(nèi)的不一致。CopyOnWriteArrayList的迭代器是只讀的,不支持寫(xiě)操作。
Set
對(duì)于Set接口來(lái)說(shuō),并發(fā)容器中主要有兩個(gè)實(shí)現(xiàn)類(lèi),一個(gè)是CopyOnWriteArraySet,另一個(gè)是ConcurrentSkipListSet。其中,
CopyOnWriteArraySet的使用場(chǎng)景、原理與注意事項(xiàng)和CopyOnWriteArrayList一致。而ConcurrentSkipListSet的使用場(chǎng)景、原理和注意事項(xiàng)和下文的ConcurrentSkipListMap一致。這里,我就不再贅述啦。
Map
在并發(fā)容器中,Map接口的實(shí)現(xiàn)類(lèi)主要有ConcurrentHashMap和ConcurrentSkipListMap,而ConcurrentHashMap和ConcurrentSkipListMap最大的區(qū)別就是:ConcurrentHashMap的Key是無(wú)序的,而ConcurrentSkipListMap的Key是有序的。
在使用ConcurrentHashMap和ConcurrentSkipListMap時(shí),需要注意的是:ConcurrentHashMap和ConcurrentSkipListMap的Key和Value都不能為空。
這里,我們可以將Map相關(guān)的類(lèi)總結(jié)成一個(gè)表格,如下所示。
Map的實(shí)現(xiàn)類(lèi)Key是否可為空Value是否可為空是否是線程安全的HashMap是是否TreeMap否是否HashTable否否是ConcurrentHashMap否否是ConcurrentSkipListMap否否是
這樣,大家記憶起來(lái)就方便多了。
這里,ConcurrentSkipListMap是基于“跳表”實(shí)現(xiàn)的,跳表的插入、刪除、查詢(xún)的平均時(shí)間復(fù)雜度為O(logn),這些時(shí)間復(fù)雜度在理論上與線程數(shù)沒(méi)有關(guān)系。如果要追求性能的話(huà),可以嘗試使用ConcurrentSkipListMap。
Queue
在Java的并發(fā)容器中,Queue相對(duì)來(lái)說(shuō)比較復(fù)雜。我們先來(lái)了解幾個(gè)概念:
阻塞隊(duì)列:阻塞一般就是指當(dāng)隊(duì)列已滿(mǎn)時(shí),入隊(duì)操作會(huì)阻塞;當(dāng)隊(duì)列為空時(shí),出隊(duì)操作就會(huì)阻塞。
非阻塞隊(duì)列:隊(duì)列的入隊(duì)和出隊(duì)操作不會(huì)阻塞。
單端隊(duì)列:隊(duì)列的入隊(duì)操作只能在隊(duì)尾進(jìn)行,隊(duì)列的出隊(duì)操作只能在隊(duì)首進(jìn)行。
雙端隊(duì)列:隊(duì)列的入隊(duì)操作和出隊(duì)操作都可以在隊(duì)首和隊(duì)尾進(jìn)行。
我們可以將上述的隊(duì)列進(jìn)行組合,將隊(duì)列分為單端阻塞隊(duì)列、雙端阻塞隊(duì)列、單端非阻塞隊(duì)列和雙端非阻塞隊(duì)列。
在Java的并發(fā)容器中,會(huì)使用明顯的標(biāo)識(shí)來(lái)區(qū)分不同類(lèi)型的隊(duì)列。
阻塞隊(duì)列一個(gè)明顯的標(biāo)識(shí)就是使用Blocking修飾,例如,ArrayBlockingQueue和LinkedBlockingQueue都是阻塞隊(duì)列。
單端隊(duì)列會(huì)使用Queue標(biāo)識(shí),例如ArrayBlockingQueue和LinkedBlockingQueue也是單端隊(duì)列。
雙端隊(duì)列會(huì)使用Deque標(biāo)識(shí),例如LinkedBlockingDeque和ConcurrentLinkedDeque都是雙端隊(duì)列。
接下來(lái),我們就分別簡(jiǎn)單聊聊這四種類(lèi)型的隊(duì)列。
單端阻塞隊(duì)列
在Java的并發(fā)容器中,單端阻塞隊(duì)列的主要實(shí)現(xiàn)是BlockingQueue,主要包括:ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、LinkedTransferQueue、PriorityBlockingQueue和DelayQueue。
單端阻塞隊(duì)列的內(nèi)部一般會(huì)有一個(gè)隊(duì)列。
在實(shí)現(xiàn)上,內(nèi)部的隊(duì)列可以是數(shù)組,例如ArrayBlockingQueue,也可以是鏈表,例如LinkedBlockingQueue。
也可以在內(nèi)部不存在隊(duì)列,例如SynchronousQueue,SynchronousQueue實(shí)現(xiàn)了生產(chǎn)者的入隊(duì)操作必須等待消費(fèi)者的出隊(duì)操作完成之后才能進(jìn)行。
LinkedTransferQueue集成了LinkedBlockingQueue和SynchronousQueue的優(yōu)點(diǎn),并且性能比LinkedBlockingQueue好。
PriorityBlockingQueue實(shí)現(xiàn)了按照優(yōu)先級(jí)進(jìn)行出隊(duì)操作,也就是說(shuō),隊(duì)列元素在PriorityBlockingQueue內(nèi)部可以按照某種規(guī)則進(jìn)行排序。
DelayQueue是延時(shí)隊(duì)列,實(shí)現(xiàn)了在一段時(shí)間后再出隊(duì)的操作。
雙端阻塞隊(duì)列
雙端阻塞隊(duì)列的實(shí)現(xiàn)主要是LinkedBlockingDeque。示意圖如下所示。
單端非阻塞隊(duì)列
單端非阻塞隊(duì)列的實(shí)現(xiàn)主要是ConcurrentLinkedQueue,示意圖如下所示。
雙端非阻塞隊(duì)列
雙端非阻塞隊(duì)列的實(shí)現(xiàn)主要是ConcurrentLinkedDeque,示意圖如下所示。
有界與無(wú)界隊(duì)列
使用隊(duì)列時(shí),還要注意隊(duì)列的有界與無(wú)界問(wèn)題,也就是在使用隊(duì)列時(shí),需要注意隊(duì)列是否有容量限制。
在實(shí)際工作中,一般推薦使用有界隊(duì)列。因?yàn)闊o(wú)界隊(duì)列很容易導(dǎo)致內(nèi)存溢出的問(wèn)題。在Java的并發(fā)容器中,只有ArrayBlockingQueue和LinkedBlockingQueue支持有界,其他的隊(duì)列都是無(wú)界隊(duì)列。
在使用時(shí),一定要注意內(nèi)存溢出問(wèn)題。
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年中職第二學(xué)年(護(hù)理)老年照護(hù)專(zhuān)項(xiàng)試題及答案
- 2025年大學(xué)本科(食品質(zhì)量與安全)食品分析試題及答案
- 2025年大學(xué)食品科學(xué)與工程(食品工程)試題及答案
- 2025年中職焊接技術(shù)與自動(dòng)化(手工焊接)試題及答案
- 養(yǎng)老院老人心理咨詢(xún)師培訓(xùn)制度
- 養(yǎng)老院心理慰藉制度
- 公共交通從業(yè)人員培訓(xùn)考核制度
- 2026年人工智能計(jì)算機(jī)視覺(jué)基礎(chǔ)知識(shí)題庫(kù)含答案
- 2026年刮痧師中醫(yī)理論考核試題含答案
- 2026年中級(jí)公共文化服務(wù)面試題及答案
- 土壤微生物群落結(jié)構(gòu)優(yōu)化研究
- 2024外研版四年級(jí)英語(yǔ)上冊(cè)Unit 4知識(shí)清單
- 四川省南充市2024-2025學(xué)年部編版七年級(jí)上學(xué)期期末歷史試題
- 國(guó)有企業(yè)三位一體推進(jìn)內(nèi)控風(fēng)控合規(guī)建設(shè)的問(wèn)題和分析
- 急診預(yù)檢分診課件教學(xué)
- 2025年高二數(shù)學(xué)建模試題及答案
- 儲(chǔ)能集裝箱知識(shí)培訓(xùn)總結(jié)課件
- 幼兒園中班語(yǔ)言《雪房子》課件
- 房地產(chǎn)項(xiàng)目開(kāi)發(fā)管理方案
- 堆垛車(chē)安全培訓(xùn)課件
- 貝林妥單抗護(hù)理要點(diǎn)
評(píng)論
0/150
提交評(píng)論