成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JDK并發(fā)編程類庫,有坑!!!

開發(fā) 前端
今天我們主要介紹了JDK1.5之后提供的并發(fā)容器,主要包括:List、Set、Map和Queue,而Queue又可以分為:?jiǎn)味俗枞?duì)列、雙端阻塞隊(duì)列、單端非阻塞隊(duì)列和雙端非阻塞隊(duì)列。對(duì)于每種并發(fā)容器,我們簡(jiǎn)單介紹了其基本原理和注意事項(xiàng)。

大家好,我是冰河~~

在JDK1.5之前的線程安全的容器,大多數(shù)都是指同步容器,使用同步容器進(jìn)行并發(fā)編程時(shí),最大的問題就是性能很差。因?yàn)橥饺萜髦械乃蟹椒ǘ际鞘褂胹ynchronized鎖進(jìn)行互斥,串行度太高了,無法真正的做到并行。

所以,在JDK1.5之后,JDK中提供了并發(fā)性能更好的容器。JDK1.5及之后的版本中,提供的線程安全的容器,一般被稱為并發(fā)容器。

并發(fā)容器

與同步容器一樣,并發(fā)容器在總體上也可以分為四大類,分別為:List、Set、Map和Queue。總體上如下圖所示。

圖片

接下來,我們分別介紹下這些并發(fā)容器在使用時(shí)的注意事項(xiàng)和避免踩到的坑。

List

并發(fā)容器中的List相對(duì)來說比較簡(jiǎn)單,就一個(gè)CopyOnWriteArrayList。大家可以從字面的意思中就能夠體會(huì)到:CopyOnWrite,在寫的時(shí)候進(jìn)行復(fù)制操作,也就是說在進(jìn)行寫操作時(shí),會(huì)將共享變量復(fù)制一份。那這樣做有什么好處呢?最大的好處就是:讀操作可以做到完全無鎖化

在CopyOnWriteArrayList內(nèi)部維護(hù)了一個(gè)數(shù)組,成員變量array指向這個(gè)數(shù)組,其核心源代碼如下所示。

private transient volatile Object[] array;
final Object[] getArray() {
 return array;
}
final void setArray(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ā)生寫操作,例如,向數(shù)組中增加一個(gè)元素時(shí),CopyOnWriteArrayList則會(huì)將內(nèi)部的數(shù)組復(fù)制一份出來,然后會(huì)在新復(fù)制出來的數(shù)組上添加新的元素,添加完再將array指向新的數(shù)組,如下圖所示。

圖片

對(duì)于CopyOnWriteArrayList的其他寫操作和添加元素的操作原理相同,這里就不再贅述了。

使用CopyOnWriteArrayList時(shí)需要注意的是:

  • CopyOnWriteArrayList只適合寫操作比較少的場(chǎng)景,并且能夠容忍讀寫操作在短時(shí)間內(nèi)的不一致。
  • CopyOnWriteArrayList的迭代器是只讀的,不支持寫操作。

Set

對(duì)于Set接口來說,并發(fā)容器中主要有兩個(gè)實(shí)現(xiàn)類,一個(gè)是CopyOnWriteArraySet,另一個(gè)是ConcurrentSkipListSet。其中,CopyOnWriteArraySet的使用場(chǎng)景、原理與注意事項(xiàng)和CopyOnWriteArrayList一致。而ConcurrentSkipListSet的使用場(chǎng)景、原理和注意事項(xiàng)和下文的ConcurrentSkipListMap一致。這里,我就不再贅述啦。

Map

在并發(fā)容器中,Map接口的實(shí)現(xiàn)類主要有ConcurrentHashMap和ConcurrentSkipListMap,而ConcurrentHashMap和ConcurrentSkipListMap最大的區(qū)別就是:ConcurrentHashMap的Key是無序的,而ConcurrentSkipListMap的Key是有序的。

在使用ConcurrentHashMap和ConcurrentSkipListMap時(shí),需要注意的是:ConcurrentHashMap和ConcurrentSkipListMap的Key和Value都不能為空。

這里,我們可以將Map相關(guān)的類總結(jié)成一個(gè)表格,如下所示。

Map的實(shí)現(xiàn)類

Key是否可為空

Value是否可為空

是否是線程安全的

HashMap




TreeMap




HashTable




ConcurrentHashMap




ConcurrentSkipListMap




這樣,大家記憶起來就方便多了。

這里,ConcurrentSkipListMap是基于“跳表”實(shí)現(xiàn)的,跳表的插入、刪除、查詢的平均時(shí)間復(fù)雜度為O(log n),這些時(shí)間復(fù)雜度在理論上與線程數(shù)沒有關(guān)系。如果要追求性能的話,可以嘗試使用ConcurrentSkipListMap。

Queue

在Java的并發(fā)容器中,Queue相對(duì)來說比較復(fù)雜。我們先來了解幾個(gè)概念:

  • 阻塞隊(duì)列:阻塞一般就是指當(dāng)隊(duì)列已滿時(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í)來區(qū)分不同類型的隊(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ì)列。

接下來,我們就分別簡(jiǎn)單聊聊這四種類型的隊(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ì)操作,也就是說,隊(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,示意圖如下所示。

圖片

有界與無界隊(duì)列

使用隊(duì)列時(shí),還要注意隊(duì)列的有界與無界問題,也就是在使用隊(duì)列時(shí),需要注意隊(duì)列是否有容量限制。

在實(shí)際工作中,一般推薦使用有界隊(duì)列。因?yàn)闊o界隊(duì)列很容易導(dǎo)致內(nèi)存溢出的問題。在Java的并發(fā)容器中,只有ArrayBlockingQueue和LinkedBlockingQueue支持有界,其他的隊(duì)列都是無界隊(duì)列。

在使用時(shí),一定要注意內(nèi)存溢出問題。

總結(jié)

今天我們主要介紹了JDK1.5之后提供的并發(fā)容器,主要包括:List、Set、Map和Queue,而Queue又可以分為:?jiǎn)味俗枞?duì)列、雙端阻塞隊(duì)列、單端非阻塞隊(duì)列和雙端非阻塞隊(duì)列。對(duì)于每種并發(fā)容器,我們簡(jiǎn)單介紹了其基本原理和注意事項(xiàng)。

責(zé)任編輯:姜華 來源: 冰河技術(shù)
相關(guān)推薦

2025-01-24 14:35:10

2022-03-09 09:43:20

并發(fā)編程Java

2022-03-02 08:20:54

并發(fā)編程java后端開發(fā)

2022-10-12 07:53:46

并發(fā)編程同步工具

2009-07-09 17:58:15

MyEclipse配置JDK類庫源代碼

2023-07-03 09:59:00

并發(fā)編程并發(fā)容器

2023-07-04 13:36:00

同步工具類Phaser

2023-07-05 08:18:54

Atomic類樂觀鎖悲觀鎖

2023-01-18 23:20:25

編程開發(fā)

2023-01-06 16:36:09

編程效率語言

2017-09-19 14:53:37

Java并發(fā)編程并發(fā)代碼設(shè)計(jì)

2011-12-12 11:16:02

iOS并發(fā)編程

2022-10-17 08:07:13

Go 語言并發(fā)編程

2024-06-24 08:11:37

2023-06-06 07:45:30

JDK21Java并發(fā)編程

2023-07-06 08:06:47

LockCondition公平鎖

2011-12-29 13:31:15

Java

2021-08-05 07:58:22

并發(fā)編程包Task

2025-02-17 00:00:25

Java并發(fā)編程

2025-02-19 00:05:18

Java并發(fā)編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 正在播放国产精品 | 一级欧美 | 黄色av免费 | 九九热在线观看 | 日韩国产三区 | 亚洲久草| 亚洲 欧美 综合 | 欧美极品一区二区 | 国产成人网 | 国产激情视频在线 | 超碰97免费在线 | 成人在线视频网址 | yiren22综合网成人 | 日韩精品一区二区三区中文在线 | 亚洲毛片在线观看 | 欧美日韩国产在线观看 | 午夜精品 | www.成人.com| 日韩成人精品在线 | 精品久久99 | 久在线 | 在线观看黄色电影 | 亚洲欧美高清 | 九九热在线视频免费观看 | 奇米av | 免费成人高清 | 国产精选一区 | 亚洲国产欧美一区二区三区久久 | 一二三区av | 国产免费视频 | 国产高清自拍视频在线观看 | 黄色免费在线观看网址 | 国产又色又爽又黄又免费 | 国产精品久久久av | 91玖玖 | 人人干人人舔 | 黄色毛片在线看 | 色欧美综合 | 久久久久久久亚洲精品 | 久久久久国产精品一区三寸 | 精品免费国产视频 |