并发修改异常。在这种情况下如何避免?
考虑下面的代码:并发修改异常。在这种情况下如何避免?
List tableData = null;
tableData = new ArrayList(records.size());
for (Iterator iter = records.iterator(); iter.hasNext();) {
Test record = (Test) iter.next();
Map rowData = createRowData(record);
if (rowData != null) {
// sorted insert
Date newDate = (Date) rowData.get(TestModel.TIMESTAMP);
boolean done = false;
for (int row = 0; row < tableData.size(); row++) {
Map currentRow = (Map) tableData.get(row);
Date currentDate = (Date) currentRow.get(TestModel.TIMESTAMP);
if (currentDate.after(newDate)) {
tableData.add(row, rowData);
done = true;
break;
}
}
if (!done) {
tableData.add(rowData);
}
}
}
} catch(Exception e) {
throw new RuntimeException("Error reading fuel and SMU data", e);
}
return tableData;
records
这里有new Vector()
正在被初始化其间。
由于ArrayList具有int容量的参数。在这种情况下如何使用CopyOnWriteArrayList
?
`STACKTRACE:
at com.mincom.explorer.uif.AbstractRequestHandler.handleException(AbstractRequestHandler.java:255)
at com.mincom.explorer.uif.AbstractRequestHandler.readData(AbstractRequestHandler.java:137)
at com.mincom.jive.service.RequestExecutor$RequestHandlerCommand.mainProcess(RequestExecutor.java:156)
at com.mincom.util.executor.AbstractCommand.run(AbstractCommand.java:56)
at com.mincom.util.executor.SimpleExecutor$WorkerThread.run(SimpleExecutor.java:156)
THROWABLE: java.lang.RuntimeException: Error reading fuel and SMU data
at minestar.production.presentation.page.fuel.smu.assistant.*.getEventsUsingFilter(*.java:243)
at minestar.production.presentation.page.fuel.smu.assistant.*.processReadData(*.java:174)
at com.mincom.explorer.uif.AbstractRequestHandler.readData(AbstractRequestHandler.java:129)
at com.mincom.jive.service.RequestExecutor$RequestHandlerCommand.mainProcess(RequestExecutor.java:156)
at com.mincom.util.executor.AbstractCommand.run(AbstractCommand.java:56)
at com.mincom.util.executor.SimpleExecutor$WorkerThread.run(SimpleExecutor.java:156)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at *.production.presentation.page.fuel.smu.assistant.*.getEventsUsingFilter(*.java:222)
... 5 more`
我已经修改了这段代码。请看一看。
您正在修改您正在使用的列表。
有两种方法可以摆脱这种情况。一种是,创建实际列表的副本,并遍历这个新列表,但修改旧列表。
List copy = copyOf(myArrayList);
for(item : copy){
//do stuff
//addon original list
myArrayList.add(item);
}
第二个是,在你的列表上向后迭代。
for(int i = list.size()-1; i >=0; i--){
//add or remove or do stuff here
}
第二个解决方案不适用于您,因为您正在将项目添加到特定索引。但如果你只需要添加/删除当前抢下项目,这将是罚款,也
注意,这是伪代码
代码中没有证据表明OP正在执行此操作。 – 2015-02-11 13:41:18
'tableData = new ArrayList .....' - >'for(int row = 0; row
确实,我忽略了内部循环。 – 2015-02-11 13:46:13
您遍历数组列表,然后通过添加特定的指数,即tableData.add(row, rowData);
数据修改它修改列表的大小。
我认为它是领先的java.util.ConcurrentModificationException
异常,更好的方法是创建另一个数组列表并向其中添加内容。
您将数据添加到List
同时,通过它迭代:
for (int row = 0; row < tableData.size(); row++) {
Map currentRow = (Map) tableData.get(row);
Date currentDate = (Date) currentRow.get(TestModel.TIMESTAMP);
if (currentDate.after(newDate)) {
tableData.add(row, rowData);
done = true;
break;
}
}
这就是为什么你得到一个ConcurrentModificationException
的原因。
CopyOnWriteArrayList
不会解决你的问题:我会建议在克隆的clonedTableData
您tableData
,并同时通过原来的tableData
迭代,添加新的记录,后来分配到tableData
“平等” clonedtableData
。 注意:这可能是一个昂贵的练习。
为什么我说“CopyOnWriteArrayList
不会解决你的问题”的原因是基于它的设计:
此数组在迭代器的生存期内不会改变,所以 干扰是不可能的,迭代器保证不会抛出
ConcurrentModificationException
。自迭代器创建了 以来,迭代器不会反映 添加,删除或更改列表。迭代器本身的元素更改操作(删除, 集合和添加)不受支持。这些方法抛出UnsupportedOperationException
。
不要在迭代时向列表添加数据。
您的类型,但您没有真正提供任何尚未在其他答案中的东西。我认为没有必要重复。 – 2016-12-10 16:21:15
从解释到底是什么引发异常开始。 – 2015-02-11 13:31:07
这个问题完全含糊不清。请提供**完整的**示例源代码以及** ConcurrentModificationException的完整**异常堆栈跟踪,我们可以尝试并复制这些代码以便准确地帮助您。 – 2015-02-11 13:31:09
@MarkoTopolnik我编辑了我的问题。 – NewBie 2015-02-11 13:37:32