自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入Java集合框架:解密List的Fail-Fast與Fail-Safe機(jī)制

開發(fā) 前端
對(duì) List 的遍歷和刪除有個(gè)更清晰的認(rèn)識(shí)!如果你正在設(shè)計(jì)一個(gè)并發(fā)系統(tǒng),選擇 fail-fast 還是 fail-safe 機(jī)制的集合類,將會(huì)顯著影響系統(tǒng)的穩(wěn)定性和性能。

圖片圖片

哈嘍,大家好呀!我是小米,今天咱們來聊聊 Java 的 List 遍歷和刪除那些事兒。這方面其實(shí)有挺多坑,特別是并發(fā)場(chǎng)景下的小細(xì)節(jié)更是容易忽略。對(duì)了,今天我們要深入探討兩個(gè)很重要的機(jī)制——快速失?。╢ail-fast)和安全失敗(fail-safe)。它們?cè)诒闅v和刪除元素時(shí)表現(xiàn)出的行為大有不同,尤其是在多線程環(huán)境下影響重大!

PART.01普通 for 循環(huán)刪除 List 指定元素

最經(jīng)典的操作,大家應(yīng)該都用過普通的 for 循環(huán)遍歷一個(gè) List 來刪除指定的元素。然而,簡單粗暴的 for 循環(huán)卻并不適用于所有情況,特別是涉及并發(fā)或動(dòng)態(tài)修改結(jié)構(gòu)時(shí)就容易出問題。

舉個(gè)例子,我們想從一個(gè)List中刪除所有偶數(shù)元素:

圖片圖片

為什么要 i-- 呢?

因?yàn)?List 是動(dòng)態(tài)的數(shù)據(jù)結(jié)構(gòu),每次刪除操作會(huì)讓后續(xù)的元素往前移動(dòng)一格,這會(huì)導(dǎo)致我們的索引不再準(zhǔn)確,容易跳過元素。試想一下,如果刪除了索引 1 的元素 2,那么原本在索引 2 的元素 3 就會(huì)移到索引 1 上去。如果沒有減一操作,循環(huán)直接跳到下一個(gè)索引,3 就會(huì)被跳過。

小結(jié)

普通 for 循環(huán)適合簡單的刪除操作,但是在多線程和并發(fā)場(chǎng)景中,普通 for 循環(huán)刪除元素會(huì)帶來一些不安全性問題,這里就需要了解 fail-fast 機(jī)制啦。

PART.02使用迭代器遍歷并刪除元素

接下來,我們看看迭代器的操作。List 的 Iterator 是更常見的遍歷方式,并且可以在遍歷時(shí)安全刪除元素——但前提是你得用對(duì)方法哦!

例如:

圖片圖片

在迭代器中,remove()方法是安全的。迭代器會(huì)維護(hù)集合的結(jié)構(gòu)變化(modCount),所以在遍歷期間不會(huì)拋出 ConcurrentModificationException 異常。

注意

在 Iterator 遍歷中,直接對(duì) List 調(diào)用 remove(i) 方法會(huì)觸發(fā) ConcurrentModificationException,因?yàn)榈鳠o法跟蹤通過 List 的直接刪除操作。下面的代碼就是個(gè)經(jīng)典反例:

圖片圖片

PART.03foreach 循環(huán)刪除元素

foreach 循環(huán)是一種簡潔的寫法,不過它也存在一些陷阱。即便在 Java 8 引入 forEachRemaining 方法后,foreach 依然無法實(shí)現(xiàn)邊遍歷邊刪除。

圖片圖片


foreach 實(shí)質(zhì)上是一個(gè)語法糖,底層依舊使用迭代器遍歷,但不支持安全刪除。為了避免異常,可以考慮先遍歷收集要?jiǎng)h除的元素,然后再進(jìn)行批量刪除。

PART.04快速失?。╢ail-fast)機(jī)制

這里要著重講一下快速失敗的機(jī)制了!fail-fast 在 Java 中主要用于檢測(cè)集合在并發(fā)修改下的結(jié)構(gòu)性變化。在遍歷過程中,如果結(jié)構(gòu)發(fā)生了變化,例如刪除了元素,Java 會(huì)立刻拋出 ConcurrentModificationException 異常。

fail-fast 機(jī)制的背后是通過一個(gè)modCount 變量來實(shí)現(xiàn)的。每次集合結(jié)構(gòu)發(fā)生變化時(shí),modCount 的值會(huì)遞增。迭代器在遍歷時(shí)會(huì)檢查 modCount 是否變化。如果變化了,說明集合被修改,就會(huì)立刻觸發(fā) ConcurrentModificationException。

這種機(jī)制的好處是讓程序及時(shí)發(fā)現(xiàn)問題,避免在集合狀態(tài)不一致的情況下繼續(xù)運(yùn)行。但是也有局限性——它不適合并發(fā)環(huán)境。如果你必須在并發(fā)場(chǎng)景下安全操作 List,就需要了解 fail-safe 機(jī)制。

PART.05安全失?。╢ail-safe)機(jī)制

那么,什么是 安全失敗(fail-safe)機(jī)制呢?

fail-safe 機(jī)制不同于 fail-fast,它不會(huì)直接訪問原集合,而是會(huì)先創(chuàng)建一個(gè)集合的副本,迭代時(shí)操作副本內(nèi)容,這樣即便原集合被修改了也不會(huì)影響到當(dāng)前遍歷。不過,這種方式的缺點(diǎn)是,遍歷期間集合的修改無法被同步感知java.util.concurrent 包下的許多集合類(如 CopyOnWriteArrayListConcurrentHashMap)都使用了 fail-safe 機(jī)制。

示例

圖片圖片

在這里,CopyOnWriteArrayList 采用了 fail-safe 機(jī)制,允許我們?cè)诒闅v期間刪除元素,不會(huì)拋出 ConcurrentModificationException。但要注意:fail-safe 并發(fā)容器會(huì)在修改時(shí)消耗較多內(nèi)存,因?yàn)樗鼤?huì)創(chuàng)建副本。

使用場(chǎng)景

在高并發(fā)場(chǎng)景下,我們推薦使用 fail-safe 容器,比如 CopyOnWriteArrayList、ConcurrentHashMap 等。它們的 fail-safe 特性不僅可以避免異常拋出,而且能夠確保在多線程環(huán)境下操作安全。但由于會(huì)創(chuàng)建副本,fail-safe 更適合讀多寫少的場(chǎng)景,否則內(nèi)存和性能消耗會(huì)非常大。

END

我們來個(gè)小總結(jié),看看這些遍歷和刪除操作的優(yōu)缺點(diǎn):

圖片圖片


希望大家讀完這篇文章,對(duì) List 的遍歷和刪除有個(gè)更清晰的認(rèn)識(shí)!如果你正在設(shè)計(jì)一個(gè)并發(fā)系統(tǒng),選擇 fail-fast 還是 fail-safe 機(jī)制的集合類,將會(huì)顯著影響系統(tǒng)的穩(wěn)定性和性能。

責(zé)任編輯:武曉燕 來源: 軟件求生
相關(guān)推薦

2023-09-14 16:10:36

機(jī)制fail-fast處理機(jī)制

2014-06-13 09:15:48

2025-01-24 08:19:57

2021-04-06 16:25:56

分布式存儲(chǔ)Fail-in-pla三副本架構(gòu)

2014-09-24 09:27:02

2024-12-24 14:40:08

2015-09-11 09:40:35

Java集合框架

2012-03-12 15:36:29

Java框架

2015-03-17 09:50:00

2020-07-15 20:32:45

fail2banFirewallD系統(tǒng)運(yùn)維

2024-09-05 10:49:42

2010-09-14 09:30:04

Java多態(tài)

2012-09-06 09:53:49

2015-01-06 09:03:18

2011-07-11 11:02:12

JAVA集合框架

2012-04-26 10:52:52

Java數(shù)組集合

2022-07-20 09:00:00

管理項(xiàng)目規(guī)模化敏捷框架科技

2019-07-22 09:59:20

Java框架集合

2015-12-10 11:04:31

2021-09-15 07:31:33

Android窗口管理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)