欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JAVA 并發(fā)容器的一些易出錯(cuò)點(diǎn)你知道嗎

 更新時(shí)間:2021年09月02日 11:00:50   作者:冰 河  
今天給大家?guī)?lái)的文章是Java并發(fā)編程的相關(guān)知識(shí),文中對(duì)java同步容器與并發(fā)容器做了非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下

并發(fā)容器

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

在這里插入圖片描述

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

List

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

在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ù)制一份出來(lái),然后會(huì)在新復(fù)制出來(lái)的數(shù)組上添加新的元素,添加完再將array指向新的數(shù)組,如下圖所示。

在這里插入圖片描述

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

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

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

Set

對(duì)于Set接口來(lái)說(shuō),并發(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是無(wú)序的,而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

這樣,大家記憶起來(lái)就方便多了。

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

Queue

在Java的并發(fā)容器中,Queue相對(duì)來(lái)說(shuō)比較復(fù)雜。我們先來(lái)了解幾個(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í)來(lái)區(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ì)列。

接下來(lái),我們就分別簡(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ì)操作,也就是說(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)題。

總結(jié)

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

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • 向量數(shù)據(jù)庫(kù)之如何使用Elasticsearch實(shí)現(xiàn)向量數(shù)據(jù)存儲(chǔ)與搜索

    向量數(shù)據(jù)庫(kù)之如何使用Elasticsearch實(shí)現(xiàn)向量數(shù)據(jù)存儲(chǔ)與搜索

    這篇文章主要介紹了向量數(shù)據(jù)庫(kù)之如何使用Elasticsearch實(shí)現(xiàn)向量數(shù)據(jù)存儲(chǔ)與搜索,在向量函數(shù)的計(jì)算過(guò)程中,會(huì)對(duì)所有匹配的文檔進(jìn)行線性掃描,因此,查詢預(yù)計(jì)時(shí)間會(huì)隨著匹配文檔的數(shù)量線性增長(zhǎng),本文給大家講解的非常詳細(xì),需要的朋友參考下吧
    2023-06-06
  • SpringBoot 使用@WebMvcTest測(cè)試MVC Web Controller

    SpringBoot 使用@WebMvcTest測(cè)試MVC Web Controller

    這篇文章主要介紹了SpringBoot 使用@WebMvcTest測(cè)試MVC Web Controller,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 深入了解java中的逃逸分析

    深入了解java中的逃逸分析

    這篇文章主要介紹了深入了解java中的逃逸分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 簡(jiǎn)述Mybatis增刪改查實(shí)例代碼

    簡(jiǎn)述Mybatis增刪改查實(shí)例代碼

    本文給大家分享編寫一個(gè)簡(jiǎn)單的mybatis進(jìn)行插入數(shù)據(jù)的實(shí)例代碼,非常不錯(cuò)具有參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-10-10
  • Mybatis-plus一對(duì)多分頁(yè)數(shù)據(jù)條數(shù)不正確的處理

    Mybatis-plus一對(duì)多分頁(yè)數(shù)據(jù)條數(shù)不正確的處理

    這篇文章主要介紹了Mybatis-plus一對(duì)多分頁(yè)數(shù)據(jù)條數(shù)不正確的處理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 解決@Scope(“prototype“)不生效的問(wèn)題

    解決@Scope(“prototype“)不生效的問(wèn)題

    這篇文章主要介紹了解決@Scope(“prototype“)不生效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 使用Java自制一個(gè)一個(gè)Nacos

    使用Java自制一個(gè)一個(gè)Nacos

    Nacos是?Dynamic?Naming?and?Configuration?Service的首字母簡(jiǎn)稱,一個(gè)更易于構(gòu)建云原生應(yīng)用的動(dòng)態(tài)服務(wù)發(fā)現(xiàn)、配置管理和服務(wù)管理平臺(tái),本文將嘗試用Java實(shí)現(xiàn)一個(gè)Nacos,感興趣的可以了解下
    2024-01-01
  • Java中從Integer到Date的轉(zhuǎn)換方法

    Java中從Integer到Date的轉(zhuǎn)換方法

    這篇文章主要介紹了Java中integer怎么轉(zhuǎn)換date,在Java中,如果我們有一個(gè)Integer類型的數(shù)據(jù),想要將其轉(zhuǎn)換為Date類型,本文給大家介紹了實(shí)現(xiàn)方法,并通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2024-05-05
  • Java的枚舉,注解和反射(二)

    Java的枚舉,注解和反射(二)

    今天小編就為大家分享一篇關(guān)于Java枚舉,注解與反射原理說(shuō)明,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2021-07-07
  • java通過(guò)isAccessAllowed方法實(shí)現(xiàn)訪問(wèn)控制

    java通過(guò)isAccessAllowed方法實(shí)現(xiàn)訪問(wèn)控制

    在Web應(yīng)用開(kāi)發(fā)中,使用Apache Shiro框架的isAccessAllowed方法可以有效管理用戶的訪問(wèn)權(quán)限,本文詳細(xì)解析了該方法的實(shí)現(xiàn)過(guò)程,包括用戶身份驗(yàn)證、權(quán)限判斷和安全性分析,下面就一起來(lái)了解一下
    2024-09-09

最新評(píng)論