【发布时间】:2013-07-23 04:31:37
【问题描述】:
我正在使用多线程来批量处理字符串列表,但是当 Runnable 任务遍历列表以处理每个字符串时出现此错误。
例如代码大致遵循这样的结构:
public class RunnableTask implements Runnable {
private List<String> batch;
RunnableTask(List<String> batch){
this.batch = batch;
}
@Override
public void run() {
for(String record : batch){
entry = record.split(",");
m = regex.matcher(entry[7]);
if (m.find() && m.group(3) != null){
currentKey = m.group(3).trim();
currentValue = Integer.parseInt(entry[4]);
if ( resultMap.get(currentKey) == null ){
resultMap.put(currentKey, currentValue);
} else {
resultMap.put(currentKey, resultMap.get(currentKey) + currentValue);
}
}
}
}
}
传递这些批处理以进行处理的线程从不修改“批处理”,并且在 for 循环内不会对批处理进行任何更改。我知道这个异常 ConcurrentModificationException 是由于在迭代期间修改了列表,但据我所知,这并没有发生。我有什么遗漏吗?
感谢您的帮助,
谢谢!
UPDATE1: 实例变量似乎不是线程安全的。我尝试使用 CopyOnWriteArrayList 代替 ArrayList 但收到不一致的结果 - 表明在以某种方式修改列表之前完整迭代没有完成,并且并非每个元素都在处理。
UPDATE2:使用同步锁和/或重入锁锁定循环仍然会出现相同的异常。
我需要一种将列表传递给 Runnable 任务的方法,并在没有新线程导致该列表出现并发问题的情况下迭代这些列表。
【问题讨论】:
-
鉴于您没有在 foreach 循环中显示代码,因此没有人知道。另外,您的列表是否在可运行文件的外部修改?
-
我敢打赌,要么调用者,要么你的循环正在修改批次。
-
循环内的处理只使用记录,不参考批处理。
-
使用列表迭代器,而不是直接遍历列表并修改它。
-
您的更新证明调用者或某人正在修改列表。 p.s.尝试使您的实例 var batch final。
标签: java multithreading list concurrency