向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
相关产品推荐
相关产品推荐

