欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java ConcurrentModificationException 深度剖析開發(fā)調試日志的解決方案

 更新時間:2025年09月05日 09:24:01   作者:熊貓釣魚>_>  
在Java多線程編程中,ConcurrentModificationException是一個常見的異常,它不僅出現(xiàn)在多線程環(huán)境,也會在單線程環(huán)境中出現(xiàn),本文深入分析這個異常的產生原因、觸發(fā)條件,并提供多種解決方案及其性能對比,幫助開發(fā)者在實際項目中做出最佳選擇,感興趣的朋友跟隨小編一起看看吧

前言

在Java多線程編程中,ConcurrentModificationException是一個常見的異常,它不僅出現(xiàn)在多線程環(huán)境,也會在單線程環(huán)境中出現(xiàn)。本文將深入分析這個異常的產生原因、觸發(fā)條件,并提供多種解決方案及其性能對比,幫助開發(fā)者在實際項目中做出最佳選擇。

異常概述

ConcurrentModificationException是Java集合框架中的一個運行時異常,它在以下情況下會被拋出:

  • 當一個線程正在迭代集合,而另一個線程同時修改了該集合的結構(添加、刪除元素)
  • 當在單線程環(huán)境中,使用迭代器遍歷集合的同時,通過集合自身的方法修改集合結構

這個異常是Java集合框架的一種**快速失敗(fail-fast)**機制,用于檢測并發(fā)修改,防止程序在不確定狀態(tài)下繼續(xù)執(zhí)行。

在我們的實際測試中,我們發(fā)現(xiàn)即使在單線程環(huán)境下,如果在遍歷過程中直接修改集合,也會拋出此異常。例如:

List<String> fruits = new ArrayList<>();
fruits.add("香蕉");
fruits.add("西瓜");
try {
    for (String fruit : fruits) {
        if (fruit.equals("香蕉")) {
            fruits.remove(fruit); // 這里會拋出ConcurrentModificationException
        }
    }
} catch (ConcurrentModificationException e) {
    System.out.println("異常信息: " + e.getMessage());
}

單線程環(huán)境下的異常分析

異常復現(xiàn)

在單線程環(huán)境下,以下代碼會觸發(fā)ConcurrentModificationException

List<String> list = new ArrayList<>();
list.add("item1");
list.add("item2");
list.add("item3");
// 使用for-each循環(huán)(底層使用Iterator)
for (String item : list) {
    if ("item2".equals(item)) {
        list.remove(item); // 這里會拋出ConcurrentModificationException
    }
}

源碼分析

為什么會拋出這個異常?讓我們看看ArrayList的Iterator實現(xiàn):

  1. 當創(chuàng)建Iterator時,會記錄當前集合的modCount值(修改計數器)到expectedModCount
  2. 每次調用next()方法時,會檢查modCount是否等于expectedModCount
  3. 如果不相等,說明集合在迭代過程中被修改,立即拋出ConcurrentModificationException

關鍵源碼(簡化版):

private class Itr implements Iterator<E> {
    int expectedModCount = modCount;
    public E next() {
        checkForComodification();
        // ...
    }
    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

在我們的測試中,我們還發(fā)現(xiàn)不僅List集合會出現(xiàn)這個問題,Map集合同樣存在類似問題:

Map<String, String> caches = new HashMap<>();
caches.put("user@getAge@123@v1", "30");
caches.put("user@getAddress@456@v1", "New York");
String sameKeyPart = "user@get";
try {
    Iterator<String> keys = caches.keySet().iterator();
    while (keys.hasNext()) {
        String key = keys.next();
        System.out.println("當前鍵: " + key);
        if (key.startsWith(sameKeyPart)) {
            caches.remove(key); // 這里會拋出ConcurrentModificationException
        }
    }
} catch (ConcurrentModificationException e) {
    System.out.println("捕獲異常: " + e.getClass().getName());
}

正確解決方法

  1. 使用Iterator的remove方法
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if ("item2".equals(item)) {
        iterator.remove(); // 正確的方式
    }
}

在我們的測試代碼中,我們驗證了這種方法的有效性:

Map<String, String> caches = new HashMap<>();
caches.put("user@getName@123@v1", "John");
caches.put("user@getEmail@123@v1", "john@example.com");
String sameKeyPart = "user@get";
Iterator<String> keys = caches.keySet().iterator();
while (keys.hasNext()) {
    String key = keys.next();
    if (key.startsWith(sameKeyPart)) {
        keys.remove(); // 使用Iterator的remove方法
        System.out.println("已刪除: " + key);
    }
}
  1. 使用Java 8+ 的removeIf方法
list.removeIf(item -> "item2".equals(item));

在我們的測試中,這種方法同樣有效:

List<String> fruits = new ArrayList<>();
fruits.add("香蕉");
fruits.add("蘋果");
fruits.add("橙子");
fruits.removeIf(fruit -> fruit.equals("香蕉"));
System.out.println("刪除后: " + fruits);

多線程環(huán)境下的異常分析

多線程環(huán)境下,即使使用了Iterator的remove方法,仍然可能發(fā)生ConcurrentModificationException,因為多個線程可能同時修改集合。

異常復現(xiàn)

List<String> list = new ArrayList<>();
// 初始化列表...
// 線程1:遍歷列表
new Thread(() -> {
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        try {
            Thread.sleep(100); // 模擬耗時操作
            String item = iterator.next(); // 可能拋出異常
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}).start();
// 線程2:修改列表
new Thread(() -> {
    try {
        Thread.sleep(50);
        list.add("newItem"); // 修改集合結構
    } catch (Exception e) {
        e.printStackTrace();
    }
}).start();

在我們的實際測試中,我們創(chuàng)建了一個更完整的示例:

private static void demoMultiThreadWithArrayList() {
    List<String> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        list.add("Item " + i);
    }
    // 創(chuàng)建一個線程用于遍歷列表
    Thread readerThread = new Thread(() -> {
        try {
            System.out.println("讀取線程開始遍歷");
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
                String item = iterator.next();
                Thread.sleep(100); // 模擬處理時間
                System.out.println("讀取線程: " + item);
            }
            System.out.println("讀取線程完成遍歷");
        } catch (ConcurrentModificationException e) {
            System.out.println("讀取線程捕獲異常: " + e.getClass().getName());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    });
    // 創(chuàng)建一個線程用于修改列表
    Thread writerThread = new Thread(() -> {
        try {
            Thread.sleep(300); // 等待讀取線程開始
            list.add("New Item"); // 添加新元素
            System.out.println("修改線程添加了新元素");
            Thread.sleep(100);
            list.remove(0); // 刪除元素
            System.out.println("修改線程刪除了元素");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    });
    writerThread.start();
    readerThread.start();
    try {
        writerThread.join();
        readerThread.join();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

線程安全分析

在多線程環(huán)境下,ArrayList等非線程安全集合存在以下問題:

  1. 結構性修改的原子性:添加或刪除元素不是原子操作
  2. 可見性問題:一個線程的修改對另一個線程不一定立即可見
  3. 一致性問題:迭代器可能看到集合的不一致狀態(tài)

解決方案對比

解決方案適用場景優(yōu)點缺點
Collections.synchronizedList讀寫頻率相近簡單易用性能較低,鎖粒度大
CopyOnWriteArrayList讀多寫少讀取無鎖,性能高寫入性能差,內存占用高
ConcurrentHashMap需要高并發(fā)Map分段鎖,性能好僅適用于Map
CopiedIterator(自定義)讀寫分離場景避免長時間鎖定額外內存開銷
快照技術一次性讀取后修改簡單直觀不適合大數據量
Stream API函數式處理代碼簡潔,可并行Java 8+才支持

在我們的測試中,我們對幾種主要的解決方案進行了實際驗證:

1. Collections.synchronizedList

List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
// 需要注意的是,遍歷時仍需要手動同步
synchronized (synchronizedList) {
    Iterator<String> iterator = synchronizedList.iterator();
    while (iterator.hasNext()) {
        String item = iterator.next();
        System.out.println("讀取線程: " + item);
    }
}

2. CopyOnWriteArrayList

List<String> copyOnWriteList = new CopyOnWriteArrayList<>();
// 可以安全地在遍歷過程中修改
for (String item : copyOnWriteList) {
    System.out.println("當前元素: " + item);
    copyOnWriteList.add("New Item"); // 不會拋出異常
}

CopiedIterator實現(xiàn)與分析

CopiedIterator是一種自定義解決方案,它在創(chuàng)建迭代器時復制集合內容,從而避免并發(fā)修改異常。

實現(xiàn)代碼

public static class CopiedIterator<E> implements Iterator<E> {
    private Iterator<E> iterator = null;
    public CopiedIterator(Iterator<E> itr) {
        LinkedList<E> list = new LinkedList<>();
        while(itr.hasNext()) {
            list.add(itr.next());
        }
        this.iterator = list.iterator();
    }
    public boolean hasNext() {
        return this.iterator.hasNext();
    }
    public void remove() {
        throw new UnsupportedOperationException("這是一個只讀迭代器");
    }
    public E next() {
        return this.iterator.next();
    }
}

使用方式

List<String> list = new ArrayList<>();
// 初始化列表...
// 創(chuàng)建CopiedIterator
Iterator<String> safeIterator;
synchronized(list) {
    safeIterator = new CopiedIterator<>(list.iterator());
}
// 安全遍歷,不會拋出ConcurrentModificationException
while(safeIterator.hasNext()) {
    String item = safeIterator.next();
    // 處理元素...
}

在我們的實際測試中,我們發(fā)現(xiàn)這種方案在特定場景下非常有效:

public static void perform() {
    Iterator<String> iterator;
    synchronized(list) {
        iterator = new CopiedIterator<>(list.iterator());
    }
    System.out.println("獲取到只讀迭代器,開始遍歷");
    while (iterator.hasNext()) {
        String item = iterator.next();
        System.out.println("遍歷元素: " + item);
        try {
            Thread.sleep(100); // 模擬處理時間
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    System.out.println("遍歷完成");
}

優(yōu)缺點分析

優(yōu)點

  • 避免了長時間鎖定集合
  • 適用于任何實現(xiàn)了Iterator接口的集合
  • 實現(xiàn)簡單,容易理解

缺點

  • 額外的內存開銷,尤其是對大型集合
  • 只能提供集合的快照,無法反映后續(xù)修改
  • 不支持修改操作(如remove)

在我們的性能測試中,我們發(fā)現(xiàn)對于包含10000個元素的列表,CopiedIterator的額外開銷大約為10-15毫秒,這對于需要長時間處理的場景來說是可以接受的。

高級解決方案

1. ConcurrentHashMap

ConcurrentHashMap是一個高性能的線程安全Map實現(xiàn),它使用分段鎖技術提高并發(fā)性能。

Map<String, String> concurrentMap = new ConcurrentHashMap<>();
// 可以安全地在遍歷過程中修改
for (String key : concurrentMap.keySet()) {
    concurrentMap.put("newKey", "newValue"); // 不會拋出異常
}

在我們的測試中,我們驗證了ConcurrentHashMap的線程安全性:

private static void demoConcurrentHashMap() {
    Map<String, String> concurrentMap = new ConcurrentHashMap<>();
    concurrentMap.put("key1", "value1");
    concurrentMap.put("key2", "value2");
    // 測試ConcurrentHashMap
    for (String key : concurrentMap.keySet()) {
        if (key.equals("key2")) {
            concurrentMap.put("key4", "value4"); // 不會拋出異常
            System.out.println("添加了新鍵值對: key4=value4");
        }
    }
    System.out.println("ConcurrentHashMap最終大小: " + concurrentMap.size());
}

2. CopyOnWriteArrayList/Set

CopyOnWriteArrayListCopyOnWriteArraySet在每次寫操作時都會復制整個底層數組,非常適合讀多寫少的場景。

List<String> cowList = new CopyOnWriteArrayList<>();
// 可以安全地在遍歷過程中修改
for (String item : cowList) {
    cowList.add("newItem"); // 不會拋出異常
}

我們的測試代碼驗證了這一點:

private static void demoCopyOnWriteArraySet() {
    // 創(chuàng)建CopyOnWriteArraySet
    Set<String> cowSet = new CopyOnWriteArraySet<>();
    cowSet.add("item1");
    cowSet.add("item2");
    cowSet.add("item3");
    System.out.println("\n嘗試在遍歷CopyOnWriteArraySet時修改:");
    for (String item : cowSet) {
        System.out.println("當前元素: " + item);
        cowSet.add("item4"); // 不會拋出異常
    }
    System.out.println("CopyOnWriteArraySet內容: " + cowSet);
}

3. 快照技術

快照技術是一種簡單的解決方案,適用于一次性讀取后修改的場景。

List<String> originalList = new ArrayList<>();
// 初始化列表...
// 創(chuàng)建快照
List<String> snapshot = new ArrayList<>(originalList);
// 遍歷快照,修改原始列表
for (String item : snapshot) {
    if (someCondition(item)) {
        originalList.remove(item);
    }
}

我們在測試中也驗證了這種技術:

private static void demoSnapshotTechnique() {
    List<String> originalList = new ArrayList<>();
    originalList.add("item1");
    originalList.add("item2");
    originalList.add("item3");
    System.out.println("原始列表: " + originalList);
    List<String> snapshot = new ArrayList<>(originalList);
    System.out.println("遍歷快照并修改原始列表:");
    for (String item : snapshot) {
        System.out.println("當前元素: " + item);
        if (item.equals("item2")) {
            originalList.remove(item);
        }
    }
    System.out.println("修改后原始列表: " + originalList);
    System.out.println("快照內容保持不變: " + snapshot);
}

4. Stream API

Java 8引入的Stream API提供了一種函數式處理集合的方式,可以避免顯式迭代。

List<String> result = list.stream()
    .filter(item -> !item.equals("item2"))
    .collect(Collectors.toList());

在我們的測試中,我們使用了Stream API的各種功能:

private static void demoStreamAPI() {
    List<String> list = new ArrayList<>();
    list.add("apple");
    list.add("banana");
    list.add("grape");
    System.out.println("\n使用Stream API過濾元素:");
    List<String> filteredList = list.stream()
        .filter(item -> !item.equals("banana"))
        .collect(Collectors.toList());
    System.out.println("過濾后: " + filteredList);
    System.out.println("\n使用Stream API轉換元素:");
    List<String> upperCaseList = list.stream()
        .map(String::toUpperCase)
        .collect(Collectors.toList());
    System.out.println("轉換后: " + upperCaseList);
}

性能測試與對比

我們對不同解決方案進行了性能測試,以下是結果分析:

1. 遍歷性能對比(10,000元素)

解決方案平均耗時(ms)
普通Iterator1-2
CopiedIterator10-15
CopyOnWriteArrayList1-2
Collections.synchronizedList3-5
Stream API (順序)5-8
Stream API (并行)2-4

在我們的性能測試代碼中,我們進行了實際測量:

private static void performanceTest() {
    // 準備大數據集
    List<String> largeList = new ArrayList<>();
    for (int i = 0; i < 10000; i++) {
        largeList.add("Item-" + i);
    }
    // 測試普通Iterator
    long startTime = System.nanoTime();
    Iterator<String> normalIterator = largeList.iterator();
    int count = 0;
    while (normalIterator.hasNext()) {
        normalIterator.next();
        count++;
    }
    long normalTime = System.nanoTime() - startTime;
    // 測試CopiedIterator
    startTime = System.nanoTime();
    Iterator<String> copiedIterator = new CopiedIterator<>(largeList.iterator());
    count = 0;
    while (copiedIterator.hasNext()) {
        copiedIterator.next();
        count++;
    }
    long copiedTime = System.nanoTime() - startTime;
    System.out.println("普通Iterator遍歷時間: " + TimeUnit.NANOSECONDS.toMillis(normalTime) + " 毫秒");
    System.out.println("CopiedIterator遍歷時間: " + TimeUnit.NANOSECONDS.toMillis(copiedTime) + " 毫秒");
    System.out.println("CopiedIterator額外開銷: " + (copiedTime - normalTime) / 1000000.0 + " 毫秒");
}

2. 修改性能對比(10,000元素,添加操作)

解決方案平均耗時(ms)
ArrayList0.1-0.2
CopyOnWriteArrayList50-100
Collections.synchronizedList0.5-1
ConcurrentHashMap (put)0.2-0.5

3. 內存占用對比

解決方案相對內存占用
ArrayList1x
CopiedIterator2x
CopyOnWriteArrayList (寫操作時)2x
快照技術2x

異常處理機制深入分析

fail-fast機制原理

Java集合框架中的fail-fast機制是一種錯誤檢測機制,它能幫助開發(fā)者盡早發(fā)現(xiàn)程序中的并發(fā)修改問題。當多個線程對集合進行結構上的改變時,就可能產生fail-fast事件。

在ArrayList中,modCount變量記錄了集合結構修改的次數。每次調用add、remove等修改結構的方法時,modCount都會增加。同時,Iterator在創(chuàng)建時會保存當前的modCount值作為expectedModCount。每次調用Iterator的next()方法時,都會檢查modCount是否與expectedModCount相等,如果不相等則拋出ConcurrentModificationException。

// ArrayList中的add方法
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
// AbstractList中的ensureCapacityInternal方法
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    modCount++; // 修改計數器增加
    ensureExplicitCapacity(minCapacity);
}

異常傳播與處理

在實際應用中,我們需要合理處理ConcurrentModificationException異常。以下是我們推薦的處理方式:

  1. 預防為主:使用線程安全的集合類或同步機制來避免異常的發(fā)生
  2. 捕獲并記錄:在無法避免異常的情況下,捕獲異常并記錄日志
  3. 優(yōu)雅降級:提供備選方案,確保系統(tǒng)在異常情況下仍能正常運行
public class SafeListProcessor {
    private List<String> dataList;
    public SafeListProcessor(List<String> dataList) {
        this.dataList = dataList;
    }
    public void processList() {
        Iterator<String> iterator = null;
        synchronized(dataList) {
            iterator = new CopiedIterator<>(dataList.iterator());
        }
        try {
            while (iterator.hasNext()) {
                String item = iterator.next();
                // 處理元素
                processItem(item);
            }
        } catch (ConcurrentModificationException e) {
            // 記錄異常日志
            System.err.println("檢測到并發(fā)修改異常: " + e.getMessage());
            // 可以選擇重試或使用備選方案
            handleConcurrentModification();
        }
    }
    private void processItem(String item) {
        // 處理單個元素
        System.out.println("處理元素: " + item);
    }
    private void handleConcurrentModification() {
        // 處理并發(fā)修改異常的備選方案
        System.out.println("使用備選方案處理數據");
    }
}

實際應用建議

選擇合適的解決方案

在實際項目中,我們需要根據具體場景選擇合適的解決方案:

  1. 讀多寫少場景
    • 推薦使用CopyOnWriteArrayList/CopyOnWriteArraySet
    • 適用于緩存、配置信息等場景
  2. 高并發(fā)讀寫場景
    • 推薦使用ConcurrentHashMap
    • 適用于需要高并發(fā)訪問的Map結構
  3. 需要長時間遍歷的場景
    • 推薦使用CopiedIterator或快照技術
    • 適用于需要對大量數據進行復雜處理的場景
  4. 簡單過濾或轉換場景
    • 推薦使用Stream API
    • 代碼簡潔,可讀性強

代碼示例

以下是我們項目中實際使用的代碼示例:

// 使用CopyOnWriteArrayList處理配置信息
public class ConfigManager {
    private CopyOnWriteArrayList<ConfigItem> configItems = new CopyOnWriteArrayList<>();
    public void addConfig(ConfigItem item) {
        configItems.add(item);
    }
    public List<ConfigItem> getActiveConfigs() {
        // 可以安全地遍歷,即使其他線程正在修改
        return configItems.stream()
            .filter(ConfigItem::isActive)
            .collect(Collectors.toList());
    }
}
// 使用ConcurrentHashMap處理用戶會話
public class SessionManager {
    private ConcurrentHashMap<String, UserSession> sessions = new ConcurrentHashMap<>();
    public void addSession(String sessionId, UserSession session) {
        sessions.put(sessionId, session);
    }
    public void cleanupExpiredSessions() {
        // 可以安全地遍歷并修改
        sessions.entrySet().removeIf(entry -> entry.getValue().isExpired());
    }
}
// 使用CopiedIterator處理長時間運行的任務
public class DataProcessor {
    private List<DataItem> dataItems;
    public void processLargeDataSet() {
        Iterator<DataItem> iterator;
        synchronized(dataItems) {
            iterator = new CopiedIterator<>(dataItems.iterator());
        }
        // 長時間處理不會阻塞其他線程對dataItems的修改
        while (iterator.hasNext()) {
            DataItem item = iterator.next();
            processComplexCalculation(item);
        }
    }
}

性能優(yōu)化建議

  1. 合理預估集合大小
    • 使用帶初始容量的構造函數避免頻繁擴容
    • 例如:new ArrayList<>(1000)而不是new ArrayList<>();
  2. 選擇合適的數據結構
    • 頻繁隨機訪問:ArrayList
    • 頻繁插入刪除:LinkedList
    • 需要排序:TreeSet/TreeMap
    • 唯一性要求:HashSet/HashMap
  3. 減少鎖競爭
    • 縮小同步塊范圍
    • 使用讀寫鎖分離讀寫操作
    • 考慮使用無鎖數據結構

最佳實踐總結

單線程環(huán)境

  1. 避免在for-each循環(huán)中修改集合
    • 使用Iterator的remove()方法
    • 使用Java 8+的removeIf()、replaceAll()等方法
    • 創(chuàng)建集合副本進行遍歷
  2. 批量操作優(yōu)于單個操作
    • 使用addAll()、removeAll()等批量方法
    • 使用Stream API進行批量處理

在我們的測試中,我們發(fā)現(xiàn)removeIf()方法特別適用于簡單的過濾操作:

List<String> fruits = new ArrayList<>();
fruits.add("香蕉");
fruits.add("蘋果");
fruits.add("橙子");
// 使用removeIf進行過濾
fruits.removeIf(fruit -> fruit.equals("香蕉"));
System.out.println("刪除后: " + fruits);

多線程環(huán)境

  1. 選擇合適的線程安全集合
    • 讀多寫少:CopyOnWriteArrayList/Set
    • 讀寫頻率相近:Collections.synchronizedList + 同步塊
    • 高并發(fā)Map:ConcurrentHashMap
  2. 避免長時間鎖定集合
    • 使用CopiedIterator或快照技術
    • 縮小同步塊范圍
  3. 考慮使用并發(fā)工具類
    • BlockingQueue系列
    • ConcurrentSkipListMap/Set

在我們的多線程測試中,我們發(fā)現(xiàn)CopyOnWriteArrayList在讀多寫少的場景下表現(xiàn)優(yōu)異:

private static void demoCopyOnWriteArrayList() {
    List<String> copyOnWriteList = new CopyOnWriteArrayList<>();
    for (int i = 0; i < 10; i++) {
        copyOnWriteList.add("Item " + i);
    }
    Thread readerThread = new Thread(() -> {
        System.out.println("讀取線程開始遍歷CopyOnWriteArrayList");
        Iterator<String> iterator = copyOnWriteList.iterator();
        while (iterator.hasNext()) {
            String item = iterator.next();
            System.out.println("讀取線程: " + item);
            try {
                Thread.sleep(100); // 模擬處理時間
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        System.out.println("讀取線程完成遍歷");
    });
    Thread writerThread = new Thread(() -> {
        try {
            System.out.println("修改線程開始修改CopyOnWriteArrayList");
            copyOnWriteList.add("New Item"); // 添加新元素
            System.out.println("修改線程添加了新元素");
            Thread.sleep(100);
            copyOnWriteList.remove(0); // 刪除元素
            System.out.println("修改線程刪除了元素");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    });
    readerThread.start();
    writerThread.start();
    try {
        readerThread.join();
        writerThread.join();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    System.out.println("最終列表大小: " + copyOnWriteList.size());
}

性能優(yōu)化

  1. 根據訪問模式選擇集合
    • 隨機訪問多:ArrayList
    • 插入刪除多:LinkedList
    • 唯一性要求:HashSet/TreeSet
  2. 預估集合大小
    • 使用構造函數指定初始容量
    • 避免頻繁擴容
  3. 減少不必要的復制
    • 謹慎使用CopyOnWrite集合
    • 優(yōu)化CopiedIterator實現(xiàn)

在我們的測試中,我們發(fā)現(xiàn)對于大數據集,Stream API的并行處理能力非常強大:

private static void demoParallelStream() {
    List<Integer> numbers = new ArrayList<>();
    for (int i = 0; i < 1000; i++) {
        numbers.add(i);
    }
    System.out.println("\n使用并行流處理大量數據:");
    long startTime = System.nanoTime();
    int sum = numbers.stream()
        .mapToInt(Integer::intValue)
        .sum();
    long sequentialTime = System.nanoTime() - startTime;
    startTime = System.nanoTime();
    int parallelSum = numbers.parallelStream()
        .mapToInt(Integer::intValue)
        .sum();
    long parallelTime = System.nanoTime() - startTime;
    System.out.println("順序流處理時間: " + TimeUnit.NANOSECONDS.toMicros(sequentialTime) + " 微秒");
    System.out.println("并行流處理時間: " + TimeUnit.NANOSECONDS.toMicros(parallelTime) + " 微秒");
    System.out.println("結果驗證: " + (sum == parallelSum ? "正確" : "錯誤"));
}

到此這篇關于Java ConcurrentModificationException 深度剖析開發(fā)調試日志的解決方案的文章就介紹到這了,更多相關Java ConcurrentModificationException調試日志內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 在IDEA中配置Selenium和WebDriver的具體操作

    在IDEA中配置Selenium和WebDriver的具體操作

    在自動化測試領域Selenium是一款非常流行的開源工具,它支持多種瀏覽器,并提供了豐富的API供開發(fā)者使用,而WebDriver則是Selenium的一個重要組件,它負責驅動瀏覽器執(zhí)行測試腳本,這篇文章主要給大家介紹了在IDEA中配置Selenium和WebDriver的具體操作,需要的朋友可以參考下
    2024-10-10
  • Java多種方式實現(xiàn)生產者消費者模式

    Java多種方式實現(xiàn)生產者消費者模式

    這篇文章主要介紹了Java多種方式實現(xiàn)生產者消費者模式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • Java 并行數據處理和性能分析

    Java 并行數據處理和性能分析

    這篇文章主要介紹了Java 并行數據處理和性能分析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • java Object wait方法詳細介紹

    java Object wait方法詳細介紹

    這篇文章主要介紹了java Object wait方法詳細介紹的相關資料,需要的朋友可以參考下
    2017-02-02
  • SpringBoot生成PDF的五種實現(xiàn)方法總結

    SpringBoot生成PDF的五種實現(xiàn)方法總結

    這篇文章主要介紹了SpringBoot生成PDF的五種實現(xiàn)方法,在開發(fā)中經常會遇到需要進行對一些數據進行動態(tài)導出PDF文件,然后讓用戶自己選擇是否需要打印出來,這篇文章我們來介紹五種實現(xiàn)方法,需要的朋友可以參考下
    2024-10-10
  • javax.mail.SendFailedException: Sending failed問題原因

    javax.mail.SendFailedException: Sending failed問題原因

    這篇文章主要介紹了javax.mail.SendFailedException: Sending failed問題原因,需要的朋友可以參考下
    2015-05-05
  • eclipse+jdk安裝以及會遇到的問題及解決方法

    eclipse+jdk安裝以及會遇到的問題及解決方法

    這篇文章主要介紹了eclipse+jdk安裝以及會遇到的問題+解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • java實現(xiàn)支付寶支付接口的調用

    java實現(xiàn)支付寶支付接口的調用

    本文主要介紹了java實現(xiàn)支付寶支付接口的調用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • SpringBoot2.0 ZipKin示例代碼

    SpringBoot2.0 ZipKin示例代碼

    這篇文章主要介紹了SpringBoot2.0 ZipKin示例代碼,詳細的介紹了什么是ZipKin以及SpringBoot2.0 ZipKin示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Java Collections.sort()排序代碼案例

    Java Collections.sort()排序代碼案例

    這篇文章主要介紹了Java Collections.sort()排序代碼案例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02

最新評論