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

向ArrayList添加元素时触发Index out of bounds异常,求助特殊场景原因及解决

解决ArrayList添加int元素时的IndexOutOfBoundsException异常

我太懂这种感受了——常规的IndexOutOfBoundsException谁没见过?要是没碰到真的特殊情况,绝对不会特意来提问。结合你说的场景:往ArrayList里加数值大概6000的普通int,还涉及一个200万大小的byte数组,这个问题的根儿完全不在元素值或者那个大数组上,而是多线程并发操作搞出来的坑。

问题根源

ArrayList本身是非线程安全的容器,当多个线程同时调用add()方法时,会触发竞态条件:

  • 假设当前ArrayList的容量刚好能容纳新元素,线程A执行完扩容检查后,还没来得及更新列表的size字段,线程B也进来做了同样的扩容检查,得出“容量足够”的结论;
  • 接着线程A完成元素添加,把size加1;
  • 线程B继续执行添加操作,这时候它用的是之前读取到的旧size值去赋值,直接超出了列表的实际可用范围,于是就抛出了IndexOutOfBoundsException。

你提到的200万大小的byte数组和6000左右的int值,只是场景里的无关变量,核心矛盾就是并发操作导致的size更新不同步。

修复方案

要解决这个问题,核心就是给ArrayList的修改操作加上同步控制,或者直接替换为线程安全的容器,这里给你几个实用的选项:

  • 同步包装器:用Collections.synchronizedList(new ArrayList<>())把普通ArrayList包装成线程安全版本,所有修改操作都会被内置的同步锁保护;
  • CopyOnWriteArrayList:如果你的场景是读多写少,这个容器会更高效——它每次修改都会复制一份新数组,读操作完全不需要锁;
  • 手动加锁:如果不想替换容器,也可以在调用add()时用synchronized代码块或者ReentrantLock包裹操作,确保同一时间只有一个线程能修改列表。

举个手动加锁的简单示例:

// 你的ArrayList实例
List<Integer> dataList = new ArrayList<>();

// 加锁后的添加操作
synchronized(dataList) {
    dataList.add(6000);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:23:20