2015-02-11 121 views
0

考虑下面的代码:并发修改异常。在这种情况下如何避免?

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` 

我已经修改了这段代码。请看一看。

+1

从解释到底是什么引发异常开始。 – 2015-02-11 13:31:07

+0

这个问题完全含糊不清。请提供**完整的**示例源代码以及** ConcurrentModificationException的完整**异常堆栈跟踪,我们可以尝试并复制这些代码以便准确地帮助您。 – 2015-02-11 13:31:09

+0

@MarkoTopolnik我编辑了我的问题。 – NewBie 2015-02-11 13:37:32

回答

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 
} 

第二个解决方案不适用于您,因为您正在将项目添加到特定索引。但如果你只需要添加/删除当前抢下项目,这将是罚款,也

注意,这是伪代码

+0

代码中没有证据表明OP正在执行此操作。 – 2015-02-11 13:41:18

+0

'tableData = new ArrayList .....' - >'for(int row = 0; row 'tableData.add ...' – Loki 2015-02-11 13:43:11

+0

确实,我忽略了内部循环。 – 2015-02-11 13:46:13

0

您遍历数组列表,然后通过添加特定的指数,即tableData.add(row, rowData);数据修改它修改列表的大小。

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

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不会解决你的问题:我会建议在克隆的clonedTableDatatableData,并同时通过原来的tableData迭代,添加新的记录,后来分配到tableData“平等” clonedtableData注意:这可能是一个昂贵的练习。

为什么我说“CopyOnWriteArrayList不会解决你的问题”的原因是基于它的设计:

此数组在迭代器的生存期内不会改变,所以 干扰是不可能的,迭代器保证不会抛出 ConcurrentModificationException。自迭代器创建了 以来,迭代器不会反映 添加,删除或更改列表。迭代器本身的元素更改操作(删除, 集合和添加)不受支持。这些方法抛出 UnsupportedOperationException

0

不要在迭代时向列表添加数据。

+0

您的类型,但您没有真正提供任何尚未在其他答案中的东西。我认为没有必要重复。 – 2016-12-10 16:21:15

相关问题