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

Java多线程并发操作ArrayList添加元素结果异常问题求解

错误原因

核心问题是你使用的ArrayList是线程不安全的容器,在没有任何并发控制的前提下,4个线程同时调用它的add()方法会产生数据竞争,最终出现元素丢失,所以每次运行得到的列表大小都是随机的,达不到预期的4000。

ArrayList的add()操作不是原子操作,内部逻辑拆解开有三步:

  • 校验底层数组的剩余容量,容量不足时先执行扩容
  • 将新元素写入数组的对应下标位置
  • 列表的size计数自增

多线程并发执行时,可能出现两个线程拿到同一个写入下标、互相覆盖元素的情况;也可能多个线程同时修改size计数,导致计数结果丢失。在JDK8及之前的版本中,这种并发写入甚至可能触发数组下标越界异常。

另外你代码最后直接打印list对象会输出全部几千个随机数,不方便核对结果,应该打印list.size()来查看最终列表长度。

修复方案

两种实现都可以满足要求,选一种即可:

方案1:使用线程安全的列表容器

直接用JDK提供的同步包装类替换原有ArrayList初始化逻辑即可,注意提前导入java.util.Collections包:

// 替换main方法中原有的列表初始化代码
List<Integer> list = Collections.synchronizedList(new ArrayList<>());

方案2:手动给写入操作加同步锁

如果要保留ArrayList的使用,可以在执行add操作时加对象锁,保证同一时间只有一个线程能操作列表:

@Override
public void run() {
    Random random = new Random();
    for (int i = 0; i < n; i++) {
        synchronized (list) {
            list.add(random.nextInt());
        }
    }
}

修改完成后再运行程序,每次得到的列表大小都会稳定为4000,符合题目要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 21:12:13