什麼是快速失敗(fail-fast)和安全失敗(fail-safe)?它們又和什麼內容有關係。以上兩點就是這篇文章的內容,廢話不多話,正文請慢用。
我們都接觸 hashmap、arraylist 這些集合類,這些在 j**a.util 包的集合類就都是快速失敗的;而 j**a.util.concurrent 包下的類都是安全失敗,比如:concurrenthashmap。
在使用迭代器對集合物件進行遍歷的時候,如果 a 執行緒正在對集合進行遍歷,此時 b 執行緒對集合進行修改(增加、刪除、修改),或者 a 執行緒在遍歷過程中對集合進行修改,都會導致 a 執行緒丟擲 concurrentmodificationexception 異常。
具體效果我們看下**:
hashmap hashmap = new hashmap();
hashmap.put("不只j**a-1", 1);
hashmap.put("不只j**a-2", 2);
hashmap.put("不只j**a-3", 3);
set set = hashmap.entryset();
iterator iterator = set.iterator();
while (iterator.hasnext())
執行後的效果如下圖:
為什麼在用迭代器遍歷時,修改集合就會拋異常時?
原因是迭代器在遍歷時直接訪問集合中的內容,並且在遍歷過程中使用乙個 modcount 變數。集合在被遍歷期間如果內容發生變化,就會改變 modcount 的值。
每當迭代器使用 hashnext()/next() 遍歷下乙個元素之前,都會檢測 modcount 變數是否為 expectedmodcount 值,是的話就返回遍歷;否則丟擲異常,終止遍歷。
明白了什麼是快速失敗之後,安全失敗也是非常好理解的。
採用安全失敗機制的集合容器,在遍歷時不是直接在集合內容上訪問的,而是先複製原有集合內容,在拷貝的集合上進行遍歷。
由於迭代時是對原集合的拷貝進行遍歷,所以在遍歷過程中對原集合所作的修改並不能被迭代器檢測到,故不會拋 concurrentmodificationexception 異常
我們上**看下是不是這樣
concurrenthashmap concurrenthashmap = new concurrenthashmap();
concurrenthashmap.put("不只j**a-1", 1);
concurrenthashmap.put("不只j**a-2", 2);
concurrenthashmap.put("不只j**a-3", 3);
set set = concurrenthashmap.entryset();
iterator iterator = set.iterator();
while (iterator.hasnext())
system.out.println("程式結束");
最後執行不會拋異常,程式正常執行。
最後說明一下,快速失敗和安全失敗是對迭代器而言的。併發環境下建議使用 j**a.util.concurrent 包下的容器類,除非沒有修改操作。
參考文章:
面試官 說說var let const之間的區別
故心故心故心故心小故衝啊 在es5中,頂層物件的屬性和全域性變數是等價的,用var宣告的變數既是全域性變數,也是頂層變數 注意 頂層物件,在瀏覽器環境指的是window物件,在 node 指的是global物件 var a 10 console.log window.a 10 使用var宣告的變數存...
面試官 說說資料庫事務吧
面試官在資料庫這方面最常問的除了sql優化,還有資料庫事務 儲存引擎等相關知識。上期有人說沒有自動門,所以這一期我特地造了自動門,這門沒有四五塊造不下來。注意 只是crud的搬磚工就不需要看了,看了也忘了,只需要拉到最後,點讚 在看 分享,一鍵三連然後收藏起來就行了。事務是指是程式中一系列嚴密的邏輯...
快速失敗Vs安全失敗 Java迭代器附示例 hg
賦值運算符號 比較運算符號 邏輯運算子 and或者 or或 not或 xor xor 不同為真,相同為假 die 輸出一條訊息,並退出當前指令碼 php view plain copy 賦值運算符號 a 5 name iwanghang 5 列印結果 5 name2 iwanghang a 列印結果...