迭代ArrayList时出现Java ConcurrentModificationException

use*_*024 2 java arraylist concurrentmodification

ConcurrentModificationException在迭代ArrayList并将对象添加到辅助节点时得到ArrayList.我真的不知道为什么,因为我没有编辑我正在迭代的列表.

这发生在我的代码的两个部分.这些是代码.

编辑 -代码1:

public static ConcurrentHashMap<Long, ArrayList<HistoricalIndex>> historicalIndexesMap = new ConcurrentHashMap<Long, ArrayList<HistoricalIndex>>();

ArrayList<HistoricalIndex> historicalIndexList = IndexService.historicalIndexesMap.get(id);
List<Double> tmpList = new ArrayList<Double>();
for(HistoricalIndex hi : historicalIndexList){ //EXCEPTION HERE
    if((System.currentTimeMillis()-hi.getTimestamp()) >= ONE_MINUTE){
        tmpList.add(hi.getIndex());
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码1中,我应该像这样复制historicalIndexList:

ArrayList<HistoricalIndex> historicalIndexList = new ArrayList<HistoricalIndex>(IndexService.historicalIndexesMap.get(id));
Run Code Online (Sandbox Code Playgroud)

而不是这样做:?

ArrayList<HistoricalIndex> historicalIndexList = IndexService.historicalIndexesMap.get(id);
Run Code Online (Sandbox Code Playgroud)

代码2:

List<Double> tmpList = new ArrayList<Double>();
for(HistoricalIndex hi : list){ //EXCEPTION HERE
    tmpList.add(hi.getIndex());
}
Run Code Online (Sandbox Code Playgroud)

有没有人知道为什么会这样?

堆栈跟踪:

21:19:50,426 ERROR [stderr] (pool-9-thread-6) java.util.ConcurrentModificationException
21:19:50,429 ERROR [stderr] (pool-9-thread-6)   at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
21:19:50,432 ERROR [stderr] (pool-9-thread-6)   at java.util.ArrayList$Itr.next(ArrayList.java:831
Run Code Online (Sandbox Code Playgroud)

Bar*_*W19 5

让我们简要了解导致ConcurrentModificationException的原因.ArrayList在内部维护一个修改计数值,该值只是一个整数,每当对列表进行修改时它就会递增.创建迭代器时,它会获取此值的"快照".然后,每次使用迭代器时,它都会检查其值的副本是否仍然与数组自己的副本匹配.如果不是,则抛出异常.

这意味着要发生ConcurrentModificationException,首次创建迭代器之后必须对ArrayList进行一些修改(即在首次执行for()语句之后但在结束之前).由于你的for()循环没有修改ArrayList,这意味着一些其他线程必须在迭代它时更改数组.

编辑:回复你的编辑,是的,你应该复制数组,如果其他线程将改变它.你甚至可以这样做:

for(HistoricalIndex hi: new ArrayList<HistoricalIndex>(historicalIndexList))
Run Code Online (Sandbox Code Playgroud)

...在开始循环时复制列表.

总而言之,ConcurrentModificationException与我们通常认为的并发问题无关.通过修改迭代器循环中的数组而不是通过迭代器的remove()方法,您可以很容易地在单个线程中获取一个.在这种情况下,"并发"意味着迭代和修改同时发生 - 无论是在相同还是不同的线程中.