首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java fail-fast 機制深度探究與避坑指南

     編輯:Java 綜合教學

什麼是 fail-fast?

集合遍歷過程中若結構被修改(增/刪元素),立即拋出 ConcurrentModificationException,而非產生不確定行為。屬於「盡力而為」的保護機制,不保證 100% 捕獲。

觸發場景

  1. 單線程:遍歷中直接調用集合的 add/remove/clear
  2. 多線程:一線程遍歷,另一線程修改結構

經典踩坑代碼

List<String> list = new ArrayList<>(Arrays.asList("a1","a2","a3"));
for (String s : list) {
    list.remove(s); // 直接修改集合 → CME
}

正確姿勢:使用 Iterator.remove()

Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if (shouldRemove(s)) it.remove(); // 安全刪除
}

原理:Iterator 內部維護 expectedModCount,調用 it.remove() 會同步更新此計數,與集合 modCount 保持一致。

Arrays.asList() 陷阱

List<String> list = Arrays.asList("a","b","c");
list.iterator().remove(); // UnsupportedOperationException

原因:Arrays.asList 返回的是 java.util.Arrays.ArrayList(內部類),未實現 remove(),非 java.util.ArrayList。此列表為固定長度視圖。

原理速覽

  • ArrayList 維護 transient int modCount
  • 構建 Iterator 時快照 expectedModCount = modCount
  • 每次 next() 前檢查 if (modCount != expectedModCount) throw CME
  • Iterator.remove() 內部調用 ArrayList.remove(index) 並同步 expectedModCount = modCount

避坑清單

  • 遍歷刪除 → Iterator.remove()
  • 遍歷新增 → 收集待加元素,遍歷後批量 addAll
  • 多線程環境 → CopyOnWriteArrayList、ConcurrentHashMap 或外部同步
  • Arrays.asList 結果不可結構性修改
  • fail-safe 集合(ConcurrentHashMap、CopyOnWriteArrayList)遍歷時不拋 CME,但可能讀到舊數據
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved