摘要:與在迭代器中的設(shè)計(jì)在中,最典型的與就是關(guān)于迭代器的設(shè)計(jì)。缺點(diǎn)是,迭代器不能正確及時(shí)的反應(yīng)集合中的內(nèi)容,而且一定程度上也增加了內(nèi)存的消耗。
fail-fast與fail-safe簡介
如果一個(gè)系統(tǒng),當(dāng)有異?;蛘咤e(cuò)誤發(fā)生時(shí)就立即中斷執(zhí)行,這種設(shè)計(jì)稱之為fail-fast。相反如果我們的系統(tǒng)可以在某種異?;蛘咤e(cuò)誤發(fā)生時(shí)繼續(xù)執(zhí)行,不會(huì)被中斷,這種設(shè)計(jì)稱之為fail-safe。
fail-fast與fail-safe在Java迭代器中的設(shè)計(jì)在Java中,最典型的fail-fast與fail-safe就是關(guān)于迭代器的設(shè)計(jì)。通常情況下,那些線程不安全的集合類產(chǎn)生的迭代器都是fail-fast的,而線程安全的集合類產(chǎn)生的迭代器是fail-safe的。fail-fast的迭代器會(huì)在迭代過程中,如果你修改了集合類里的內(nèi)容,則會(huì)拋出ConcurrentModificationException異常。fail-safe的迭代器則可以在迭代過程中任意修改集合類的內(nèi)容,不會(huì)有異常拋出。
Java的fail-fast迭代器前面說過,線程安全的集合類產(chǎn)生的迭代器是基于fail-fast設(shè)計(jì)的,例如ArrayList。這種迭代器迭代過程中是直接訪問原數(shù)據(jù)信息的,所以當(dāng)原集合內(nèi)容修改了后,迭代器不能保證正確的迭代過程。代碼示例如下:
public static void failFast() { Listlist = new ArrayList<>(); list.add("item-1"); list.add("item-2"); list.add("item-3"); list.add("item-4"); Iterator it = list.iterator(); while (it.hasNext()) { String item = it.next(); System.out.println(item); list.add("itme-5"); // 下次迭代時(shí)會(huì)拋出ConcurrentModificationException異常 } }
通過分析ArrayList源碼可以看出,當(dāng)對(duì)ArrayList做添加或者刪除元素的操作時(shí),都會(huì)修改modCount這個(gè)變量,而ArrayList的迭代器每次迭代的時(shí)候,又都回去檢查當(dāng)前modCount和迭代器產(chǎn)生時(shí)的expectedModCount變量是否相等,如果不等就會(huì)拋出ConcurrentModificationException異常。
protected transient int modCount = 0; public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! // 上面那個(gè)方法調(diào)用后會(huì)修改modCount .... } // ArrayList的迭代器 private class Itr implements IteratorJava的fail-safe迭代器{ public E next() { checkForComodification(); ... } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } ... }
對(duì)于那些線程安全的集合類,在調(diào)用iterator方法產(chǎn)生迭代器的時(shí)候,會(huì)將當(dāng)前集合的素有元素都做一個(gè)快照,即復(fù)制一份副本。每次迭代的時(shí)候都是訪問這個(gè)快照內(nèi)的元素,而不是原集合的元素。代碼示例如下:
public static void failSafe() { Listlist = new CopyOnWriteArrayList<>(); list.add("item-1"); list.add("item-2"); list.add("item-3"); list.add("item-4"); Iterator it = list.iterator(); while (it.hasNext()) { String item = it.next(); System.out.println(item); list.add("itme-5"); } System.out.println(list.size()); // 會(huì)打印出來8,迭代四次,四個(gè)新元素插入到了集合中。 }
這種設(shè)計(jì)的好處是保證了在多線程操縱同一個(gè)集合的時(shí)候,不會(huì)因?yàn)槟硞€(gè)線程修改了集合,而影響其他正在迭代訪問集合的線程。缺點(diǎn)是,迭代器不能正確及時(shí)的反應(yīng)集合中的內(nèi)容,而且一定程度上也增加了內(nèi)存的消耗。
迭代器小提示如果用Java的for loop來訪問集合,原理上還是用迭代器的方式,所以下面的代碼同樣會(huì)拋出ConcurrentModificationException異常。
Listlist = new ArrayList<>(); list.add("item-1"); list.add("item-2"); list.add("item-3"); list.add("item-4"); for (String item : list) { System.err.println(item); list.add("itme-5"); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69187.html
摘要:注意,迭代器的快速失敗行為無法得到保證,因?yàn)橐话銇碚f,不可能對(duì)是否出現(xiàn)不同步并發(fā)修改做出任何硬性保證??焖偈〉鲿?huì)盡最大努力拋出。 fail-fast與fail-safe 在Collection集合的各個(gè)類中,有線程安全和線程不安全這2大類的版本。 對(duì)于線程不安全的類,并發(fā)情況下可能會(huì)出現(xiàn)fail-fast情況;而線程安全的類,可能出現(xiàn)fail-safe的情況。 一、并發(fā)修改 當(dāng)一...
摘要:一什么是機(jī)制在用迭代器遍歷集合時(shí)當(dāng)集合的結(jié)構(gòu)被修改會(huì)拋出異常二什么情況下集合的結(jié)構(gòu)會(huì)被修改單線程環(huán)境集合在遍歷的過程中如果要對(duì)集合進(jìn)行增刪操作沒有調(diào)用迭代器的方法而是用的集合自身的方法則可能會(huì)產(chǎn)生事件多線程環(huán)境下當(dāng)一個(gè)線程在遍歷某個(gè)集合 一.什么是fail-fast機(jī)制? 在用迭代器遍歷集合時(shí),當(dāng)集合的結(jié)構(gòu)被修改,會(huì)拋出ConcurrentModificationException異常...
摘要:體現(xiàn)的就是適配器模式。數(shù)組對(duì)象集合世界中的機(jī)制機(jī)制集合世界中比較常見的錯(cuò)誤檢測機(jī)制,防止在對(duì)集合進(jìn)行遍歷過程當(dāng)中,出現(xiàn)意料之外的修改,會(huì)通過異常暴力的反應(yīng)出來。而在增強(qiáng)循環(huán)中,集合遍歷是通過進(jìn)行的。 前言 學(xué)習(xí)情況記錄 時(shí)間:week 2 SMART子目標(biāo) :Java 容器 記錄在學(xué)習(xí)Java容器 知識(shí)點(diǎn)中,關(guān)于List的重點(diǎn)知識(shí)點(diǎn)。 知識(shí)點(diǎn)概覽: 容器中的設(shè)計(jì)模式 從Array...
摘要:我們都接觸這些集合類,這些在包的集合類就都是快速失敗的而包下的類都是安全失敗,比如。安全失敗明白了什么是快速失敗之后,安全失敗也是非常好理解的。最后說明一下,快速失敗和安全失敗是對(duì)迭代器而言的。 什么是快速失?。╢ail-fast)和安全失敗(fail-safe)?它們又和什么內(nèi)容有關(guān)系。以上兩點(diǎn)就是這篇文章的內(nèi)容,廢話不多話,正文請(qǐng)慢用。 我們都接觸 HashMap、ArrayLis...
摘要:什么是線程餓死,什么是活鎖多線程中的忙循環(huán)是什么變量是什么變量和變量有什么不同類型變量提供什么保證能使得一個(gè)非原子操作變成原子操作嗎 JVM專題 showImg(https://segmentfault.com/img/remote/1460000019943435); (面試題+答案領(lǐng)取方式見個(gè)人主頁) Java 類加載過程? 描述一下 JVM 加載 Class 文件的原理機(jī)制? ...
閱讀 1616·2021-09-24 10:38
閱讀 1539·2021-09-22 15:15
閱讀 3096·2021-09-09 09:33
閱讀 926·2019-08-30 11:08
閱讀 669·2019-08-30 10:52
閱讀 1278·2019-08-30 10:52
閱讀 2371·2019-08-28 18:01
閱讀 548·2019-08-28 17:55