并发修改异常。在这种情况下如何避免?

时间:2015-02-11 13:28:43

标签: java arraylist concurrentmodification

请考虑以下代码:

 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 capacity。如何在此方案中使用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`

我再次修改了这段代码。请看看。

4 个答案:

答案 0 :(得分:0)

您正在修改列表,您正在使用。

有两种方法可以摆脱这种情况。一个是,创建一个实际列表的副本,并迭代这个新列表,但修改旧列表。

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
}

第二个解决方案不适合您,因为您要在特定索引上添加项目。但是如果你只是添加/删除当前抓取的项目,那也没关系

注意,这是伪代码

答案 1 :(得分:0)

您正在迭代数组列表,然后通过在特定索引处添加tableData.add(row, rowData);数据来修改它,即修改列表的大小。

我认为它是领先的java.util.ConcurrentModificationException异常,更好的方法是创建另一个数组列表并在其中添加内容。

答案 2 :(得分:0)

您正在迭代它时将数据添加到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无法解决您的问题:我建议克隆您的tableData并在浏览原始tableData时,在clonedTableData及以后添加新记录将tableData分配给“等于”clonedtableData注意:这可能是一项昂贵的练习。

为什么我说“CopyOnWriteArrayList无法解决您的问题”的原因是基于它的设计:

  

这个数组在迭代器的生命周期中永远不会改变,所以   干扰是不可能的,并且保证迭代器不会抛出   ConcurrentModificationException。迭代器不会反映出来   自迭代器以来添加,删除或更改列表   创建。对迭代器本身进行元素更改操作(删除,   不支持set和add)。抛出这些方法   UnsupportedOperationException

答案 3 :(得分:0)

在迭代时,不要将数据添加到列表中。