2015-02-11 177 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

相關問題