摘要:我們都接觸這些集合類,這些在包的集合類就都是快速失敗的而包下的類都是安全失敗,比如。安全失敗明白了什么是快速失敗之后,安全失敗也是非常好理解的。最后說(shuō)明一下,快速失敗和安全失敗是對(duì)迭代器而言的。
什么是快速失敗(fail-fast)和安全失敗(fail-safe)?它們又和什么內(nèi)容有關(guān)系。以上兩點(diǎn)就是這篇文章的內(nèi)容,廢話不多話,正文請(qǐng)慢用。
我們都接觸 HashMap、ArrayList 這些集合類,這些在 java.util 包的集合類就都是快速失敗的;而 java.util.concurrent 包下的類都是安全失敗,比如:ConcurrentHashMap。
1. 快速失敗(fail-fast)在使用迭代器對(duì)集合對(duì)象進(jìn)行遍歷的時(shí)候,如果 A 線程正在對(duì)集合進(jìn)行遍歷,此時(shí) B 線程對(duì)集合進(jìn)行修改(增加、刪除、修改),或者 A 線程在遍歷過(guò)程中對(duì)集合進(jìn)行修改,都會(huì)導(dǎo)致 A 線程拋出 ConcurrentModificationException 異常。
具體效果我們看下代碼:
HashMap hashMap = new HashMap(); hashMap.put("不只Java-1", 1); hashMap.put("不只Java-2", 2); hashMap.put("不只Java-3", 3); Set set = hashMap.entrySet(); Iterator iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); hashMap.put("下次循環(huán)會(huì)拋異常", 4); System.out.println("此時(shí) hashMap 長(zhǎng)度為" + hashMap.size()); }
執(zhí)行后的效果如下圖:
為什么在用迭代器遍歷時(shí),修改集合就會(huì)拋異常時(shí)?
原因是迭代器在遍歷時(shí)直接訪問集合中的內(nèi)容,并且在遍歷過(guò)程中使用一個(gè) modCount 變量。集合在被遍歷期間如果內(nèi)容發(fā)生變化,就會(huì)改變 modCount 的值。
每當(dāng)?shù)魇褂?hashNext()/next() 遍歷下一個(gè)元素之前,都會(huì)檢測(cè) modCount 變量是否為 expectedModCount 值,是的話就返回遍歷;否則拋出異常,終止遍歷。
2. 安全失敗(fail-safe)明白了什么是快速失敗之后,安全失敗也是非常好理解的。
采用安全失敗機(jī)制的集合容器,在遍歷時(shí)不是直接在集合內(nèi)容上訪問的,而是先復(fù)制原有集合內(nèi)容,在拷貝的集合上進(jìn)行遍歷。
由于迭代時(shí)是對(duì)原集合的拷貝進(jìn)行遍歷,所以在遍歷過(guò)程中對(duì)原集合所作的修改并不能被迭代器檢測(cè)到,故不會(huì)拋 ConcurrentModificationException 異常
我們上代碼看下是不是這樣
ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap(); concurrentHashMap.put("不只Java-1", 1); concurrentHashMap.put("不只Java-2", 2); concurrentHashMap.put("不只Java-3", 3); Set set = concurrentHashMap.entrySet(); Iterator iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); concurrentHashMap.put("下次循環(huán)正常執(zhí)行", 4); } System.out.println("程序結(jié)束");
運(yùn)行效果如下,的確不會(huì)拋異常,程序正常執(zhí)行。
最后說(shuō)明一下,快速失敗和安全失敗是對(duì)迭代器而言的。并發(fā)環(huán)境下建議使用 java.util.concurrent 包下的容器類,除非沒有修改操作。
我是七淅 (xī),后臺(tái)回復(fù)「Java」,送你 13 本 Java 經(jīng)典電子書。公眾號(hào)專注分享 Java 干貨、讀書筆記、成長(zhǎng)思考。
參考文章:
https://blog.csdn.net/qq_3178...
如果你喜歡本文,歡迎來(lái)微信公眾號(hào)「不只Java」和我一起學(xué)(wan)習(xí)(shua)。后臺(tái)回復(fù)「Java」,送你 13 本 Java 經(jīng)典電子書。公眾號(hào)專注分享 Java 干貨、讀書筆記、成長(zhǎng)思考
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/72105.html
摘要:什么是線程餓死,什么是活鎖多線程中的忙循環(huán)是什么變量是什么變量和變量有什么不同類型變量提供什么保證能使得一個(gè)非原子操作變成原子操作嗎 JVM專題 showImg(https://segmentfault.com/img/remote/1460000019943435); (面試題+答案領(lǐng)取方式見個(gè)人主頁(yè)) Java 類加載過(guò)程? 描述一下 JVM 加載 Class 文件的原理機(jī)制? ...
摘要:第二天相同的時(shí)間相同的地方,我卻走錯(cuò)了地方,原來(lái)成都騰訊大廈有兩棟。 在一個(gè)雨蒙蒙的清晨,百般無(wú)聊的閑逛中,突然回憶起了我這一生中的第一次面試經(jīng)歷。雖然結(jié)果是以失敗而告終,但此時(shí)此刻的回憶,帶給我的并不是失敗而是成長(zhǎng)。 作為一名實(shí)習(xí)生,我深刻的感受到在校園與社會(huì)夾縫中生活的不易。也十分的幸運(yùn),我還有足夠的青春與活力驅(qū)動(dòng)著我去學(xué)習(xí),讓我的未來(lái)不再遙不可及;讓我能在社會(huì)的這份土壤里扎根成長(zhǎng)...
摘要:第二天相同的時(shí)間相同的地方,我卻走錯(cuò)了地方,原來(lái)成都騰訊大廈有兩棟。 在一個(gè)雨蒙蒙的清晨,百般無(wú)聊的閑逛中,突然回憶起了我這一生中的第一次面試經(jīng)歷。雖然結(jié)果是以失敗而告終,但此時(shí)此刻的回憶,帶給我的并不是失敗而是成長(zhǎng)。 作為一名實(shí)習(xí)生,我深刻的感受到在校園與社會(huì)夾縫中生活的不易。也十分的幸運(yùn),我還有足夠的青春與活力驅(qū)動(dòng)著我去學(xué)習(xí),讓我的未來(lái)不再遙不可及;讓我能在社會(huì)的這份土壤里扎根成長(zhǎng)...
摘要:第二天相同的時(shí)間相同的地方,我卻走錯(cuò)了地方,原來(lái)成都騰訊大廈有兩棟。 在一個(gè)雨蒙蒙的清晨,百般無(wú)聊的閑逛中,突然回憶起了我這一生中的第一次面試經(jīng)歷。雖然結(jié)果是以失敗而告終,但此時(shí)此刻的回憶,帶給我的并不是失敗而是成長(zhǎng)。 作為一名實(shí)習(xí)生,我深刻的感受到在校園與社會(huì)夾縫中生活的不易。也十分的幸運(yùn),我還有足夠的青春與活力驅(qū)動(dòng)著我去學(xué)習(xí),讓我的未來(lái)不再遙不可及;讓我能在社會(huì)的這份土壤里扎根成長(zhǎng)...
閱讀 2722·2021-11-11 17:21
閱讀 613·2021-09-23 11:22
閱讀 3578·2019-08-30 15:55
閱讀 1640·2019-08-29 17:15
閱讀 573·2019-08-29 16:38
閱讀 904·2019-08-26 11:54
閱讀 2503·2019-08-26 11:53
閱讀 2749·2019-08-26 10:31