You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java多线程生成ConcurrentModificationException场景的问题咨询

问题分析与解决方案

原代码抛出IllegalThreadStateException的原因

你原代码的问题出在重复启动同一个线程:

  • Thread类的start()方法只能调用一次,调用后线程会从NEW状态进入RUNNABLE状态,后续再次调用start()就会抛出IllegalThreadStateException。
  • 你用l.forEach()遍历列表(初始有4个元素),每次遍历都会执行t1.start()和t2.start(),相当于每个线程被启动了4次,第一次启动后线程状态不再是NEW,后续启动操作直接触发异常。

正确触发ConcurrentModificationException的多线程示例

首先要明确:CopyOnWriteArrayList是线程安全的集合,它采用写时复制机制,遍历操作会基于列表的快照进行,所以不会抛出ConcurrentModificationException。要触发这个异常,得用非线程安全的集合(比如ArrayList),结合多线程下的遍历+修改操作。

以下是符合需求的示例代码:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ConcurrentModificationDemo {
    public static void main(String[] args) {
        // 使用非线程安全的ArrayList,这是触发异常的前提
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4));

        // 线程1:遍历列表(依赖ArrayList的fail-fast迭代器)
        Thread thread1 = new Thread(() -> {
            try {
                // 延迟100ms,让线程2先开始修改列表
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            // for-each循环本质是用迭代器遍历,会触发fail-fast检查
            for (Integer num : list) {
                System.out.println("线程1遍历元素:" + num);
                try {
                    // 每次遍历后延迟,放大并发冲突的概率
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        // 线程2:修改列表结构(添加元素)
        Thread thread2 = new Thread(() -> {
            try {
                // 延迟50ms,确保线程1已经准备好遍历
                Thread.sleep(50);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            for (int i = 5; i < 8; i++) {
                System.out.println("线程2添加元素:" + i);
                list.add(i);
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}

异常触发原理

ArrayList的迭代器实现了fail-fast机制:迭代器初始化时会记录当前列表的修改次数modCount,遍历过程中每次都会检查这个值是否和预期一致。如果另一个线程修改了列表的结构(比如add/remove操作),modCount会递增,此时迭代器发现值不一致,就会抛出ConcurrentModificationException。

内容的提问来源于stack exchange,提问作者D_B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:33:15