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

多執行緒安全迭代:複製迭代器模式解決 ConcurrentModificationException

     編輯:Java 程式設計入門

問題根源

當一個執行緒正在遍歷集合(Iterator),另一執行緒修改該集合(增/刪元素),即拋出 ConcurrentModificationException。直接同步整個遍歷過程雖能解決,但若遍歷涉及複雜運算或 I/O,鎖持有時間過長會嚴重降低併發吞吐。

解決方案:快照式唯讀迭代器

核心思想:在同步區塊內快速複製元素到新容器,釋放鎖後對副本進行唯讀遍歷。

實作範例

private final List<Object> list = new ArrayList<>();

public void add(Object obj) {
    synchronized (list) { list.add(obj); }
}

public void perform() {
    Iterator<Object> snapshotIter;
    synchronized (list) {
        // 快照複製:僅複製引用,極快
        snapshotIter = new CopiedIterator(list.iterator());
    }
    // 無鎖遍歷,可執行耗時操作
    while (snapshotIter.hasNext()) {
        process(snapshotIter.next());
    }
}

CopiedIterator 實作

public class CopiedIterator<E> implements Iterator<E> {
    private final Iterator<E> delegate;
    public CopiedIterator(Iterator<E> source) {
        List<E> copy = new ArrayList<>();
        while (source.hasNext()) copy.add(source.next());
        this.delegate = copy.iterator();
    }
    @Override public boolean hasNext() { return delegate.hasNext(); }
    @Override public E next() { return delegate.next(); }
    @Override public void remove() { throw new UnsupportedOperationException("唯讀快照,不可移除"); }
}

關鍵特性與取捨

適用場景與替代方案

  • 適用:讀多寫少、遍歷耗時、可接受稍舊資料的報表、匯出、批次處理
  • 不適用:強一致性要求、極大集合(記憶體壓力)、需邊遍歷邊修改
  • 現代替代:JDK 8+ CopyOnWriteArrayList(寫時複製)、Stream API 並行流、不可變集合

掌握「複製迭代器」模式,是解決高併發下集合遍歷衝突的經典利器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性說明
執行緒安全遍歷期間不持有原集合鎖,極大縮短臨界區
資料一致性屬於「弱一致性」:遍歷見的是複製那一刻的快照,後續異動不可見
功能限制不支援 remove(),非即時視圖
記憶體開銷O(N) 額外空間,N 為元素數量