摘要:與在迭代器中的設計在中,最典型的與就是關于迭代器的設計。缺點是,迭代器不能正確及時的反應集合中的內容,而且一定程度上也增加了內存的消耗。
fail-fast與fail-safe簡介
如果一個系統,當有異常或者錯誤發生時就立即中斷執行,這種設計稱之為fail-fast。相反如果我們的系統可以在某種異常或者錯誤發生時繼續執行,不會被中斷,這種設計稱之為fail-safe。
fail-fast與fail-safe在Java迭代器中的設計在Java中,最典型的fail-fast與fail-safe就是關于迭代器的設計。通常情況下,那些線程不安全的集合類產生的迭代器都是fail-fast的,而線程安全的集合類產生的迭代器是fail-safe的。fail-fast的迭代器會在迭代過程中,如果你修改了集合類里的內容,則會拋出ConcurrentModificationException異常。fail-safe的迭代器則可以在迭代過程中任意修改集合類的內容,不會有異常拋出。
Java的fail-fast迭代器前面說過,線程安全的集合類產生的迭代器是基于fail-fast設計的,例如ArrayList。這種迭代器迭代過程中是直接訪問原數據信息的,所以當原集合內容修改了后,迭代器不能保證正確的迭代過程。代碼示例如下:
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"); // 下次迭代時會拋出ConcurrentModificationException異常 } }
通過分析ArrayList源碼可以看出,當對ArrayList做添加或者刪除元素的操作時,都會修改modCount這個變量,而ArrayList的迭代器每次迭代的時候,又都回去檢查當前modCount和迭代器產生時的expectedModCount變量是否相等,如果不等就會拋出ConcurrentModificationException異常。
protected transient int modCount = 0; public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! // 上面那個方法調用后會修改modCount .... } // ArrayList的迭代器 private class Itr implements IteratorJava的fail-safe迭代器{ public E next() { checkForComodification(); ... } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } ... }
對于那些線程安全的集合類,在調用iterator方法產生迭代器的時候,會將當前集合的素有元素都做一個快照,即復制一份副本。每次迭代的時候都是訪問這個快照內的元素,而不是原集合的元素。代碼示例如下:
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()); // 會打印出來8,迭代四次,四個新元素插入到了集合中。 }
這種設計的好處是保證了在多線程操縱同一個集合的時候,不會因為某個線程修改了集合,而影響其他正在迭代訪問集合的線程。缺點是,迭代器不能正確及時的反應集合中的內容,而且一定程度上也增加了內存的消耗。
迭代器小提示如果用Java的for loop來訪問集合,原理上還是用迭代器的方式,所以下面的代碼同樣會拋出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"); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69187.html
摘要:注意,迭代器的快速失敗行為無法得到保證,因為一般來說,不可能對是否出現不同步并發修改做出任何硬性保證。快速失敗迭代器會盡最大努力拋出。 fail-fast與fail-safe 在Collection集合的各個類中,有線程安全和線程不安全這2大類的版本。 對于線程不安全的類,并發情況下可能會出現fail-fast情況;而線程安全的類,可能出現fail-safe的情況。 一、并發修改 當一...
摘要:一什么是機制在用迭代器遍歷集合時當集合的結構被修改會拋出異常二什么情況下集合的結構會被修改單線程環境集合在遍歷的過程中如果要對集合進行增刪操作沒有調用迭代器的方法而是用的集合自身的方法則可能會產生事件多線程環境下當一個線程在遍歷某個集合 一.什么是fail-fast機制? 在用迭代器遍歷集合時,當集合的結構被修改,會拋出ConcurrentModificationException異常...
摘要:體現的就是適配器模式。數組對象集合世界中的機制機制集合世界中比較常見的錯誤檢測機制,防止在對集合進行遍歷過程當中,出現意料之外的修改,會通過異常暴力的反應出來。而在增強循環中,集合遍歷是通過進行的。 前言 學習情況記錄 時間:week 2 SMART子目標 :Java 容器 記錄在學習Java容器 知識點中,關于List的重點知識點。 知識點概覽: 容器中的設計模式 從Array...
摘要:我們都接觸這些集合類,這些在包的集合類就都是快速失敗的而包下的類都是安全失敗,比如。安全失敗明白了什么是快速失敗之后,安全失敗也是非常好理解的。最后說明一下,快速失敗和安全失敗是對迭代器而言的。 什么是快速失敗(fail-fast)和安全失敗(fail-safe)?它們又和什么內容有關系。以上兩點就是這篇文章的內容,廢話不多話,正文請慢用。 我們都接觸 HashMap、ArrayLis...
閱讀 1571·2021-09-24 10:38
閱讀 1498·2021-09-22 15:15
閱讀 3059·2021-09-09 09:33
閱讀 905·2019-08-30 11:08
閱讀 638·2019-08-30 10:52
閱讀 1253·2019-08-30 10:52
閱讀 2344·2019-08-28 18:01
閱讀 520·2019-08-28 17:55