2014-06-30 35 views
1

我不知道爲什麼當我迭代ArrayList時發生ConcurrentModificationException。 ArrayList是methode的作用域,所以它不應該被執行相同代碼的其他線程看到。至少如果我正確地理解了多線程和變量作用域。ArrayLists上ConcurrentModificationException的原因iterator.next()

Caused by: java.util.ConcurrentModificationException 
at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:64) 
at com....StrategyHandler.applyStrategy(StrategyHandler.java:184) 

private List<Order> applyStrategy(StorageObjectTree storageObjectTree) { 
    ... 
    List<OrderHeader> finalList = new ArrayList<Order>(); 

    for (StorageObject storageObject : storageObjectTree.getStorageObjects()) { 

     List<Order> currentOrders = strategy.process(storageObject); 
     ... 
     if (currentOrders != null) { 
      Iterator<Order> iterator = currentOrders.iterator(); 
      while (iterator.hasNext()) { 
      Order order = (Order) iterator.next();  // line 64 
      // read some values from order 
      } 

      finalList.addAll(currentOrders); 
     } 
    } 

    return finalList; 
} 

有人可以給我一個提示什麼可能是問題的根源?

+0

不要將iterator.next()轉換爲Order – newbieee

+4

@newbieee:雖然轉換是不必要的,但這不是問題的原因。 –

+1

你沒有添加或刪除currentOrders的任何值的權利? – paul

回答

1

如果您已經閱讀Java文檔的ConcurrentModifcationException

它明確規定在它發生的條件:已檢測到併發 修改對象的

此異常可以通過以下方法拋出當這種修改是不允許的。 例如,一個線程在另一個線程遍歷它時通常不允許修改Collection。一般而言,在這些情況下迭代的結果是不確定的。 某些迭代器實現(包括由JRE提供的所有通用 目的集合實現的實現)可能選擇 如果檢測到此行爲則拋出此異常。迭代器做 這就是所謂的快速迭代器,因爲它們很快就會失敗,並且會在未來的未定時間冒着任意的非確定性行爲冒險。

請注意,此例外情況並不總是表明某個對象已由另一個線程同時修改了 。如果單個線程 發出一系列方法調用違反對象的合約 ,該對象可能會拋出此異常。例如,如果 線程正在使用故障快速迭代器迭代 集合時直接修改集合,則迭代器將拋出此異常。

請注意,無法保證故障快速行爲,因爲它通常是 說話,不可能在出現 非同步併發修改時作出任何硬性保證。盡力而爲,快速失敗操作拋出 ConcurrentModificationException。因此, 將是錯誤的編寫依賴於此異常 其正確性的程序:ConcurrentModificationException的應該只是 檢測錯誤。

就你所說的,你沒有多個線程訪問這個列表。如果你正在從迭代器讀取的單個線程也可能試圖寫入它,那麼按照上面的第二段,它仍然是可能的。

希望這會有所幫助。

0

當您更改/添加/從列表中刪除值並且在迭代它的同時發生此異常。如果你同時使用多個線程...

嘗試圍繞你的如果通過synchronized(currentOrders) { /* YOUR LAST CODE */ }。 我不確定這一點,但嘗試它。

0

取決於strategy.process(..)的實現,它可能是該實現仍然引用它作爲結果返回的List。如果在此實現中涉及多個線程,則可能是由於其中一個線程修改了該列表,即使它作爲結果返回後也是如此。如果你知道「未來」模式,你可以想象一個方法,一個方法立即返回一個空列表,並在稍後使用另一個線程添加實際結果)

你可以嘗試創建一個新的ArrayList「around」結果列表並遍歷這個複製的列表。

0

您可能想要閱讀this SO貼子。基本上切換並使用CopyOnWriteArrayList如果你不能看到問題來自哪裏。

相關問題