2011-01-11 16 views
1

迭代列表或映射的哪個代碼序列可防止出現ConcurrentModificationException?在我們的代碼中,我們有多次和零星的ConcurrentModificationException。這個問題有兩個原因。防止Java中出現零星的ConcurrentModificationException的最佳做法是什麼?

  1. 另一個線程變化對迭代
  2. 這就是所謂在環是改變列表的方法的列表。

問題1可以通過在循環周圍同步來解決。但是,如果外部代碼在循環中被稱爲原因2,則這是不好的。

問題2可以通過列表或映射的副本來解決。

這意味着列表或映射必須在循環前複製到同步塊中。有更好的解決方案嗎?

一些示例代碼:

public void todoSomeThings(Map<Abc, Object> map){ 
    for(Abc abc : map.keySet()){ 
     abc.todoSomeThings(); 
    } 
} 

回答

3

一個公平的警告:使用潔悠神(java.util.concurrent中)將刪除錯誤,但你會運行到可能是最壞的情況,即種族的更新,陳舊的讀取等。最好的做法是

瞭解你數據結構,使用狀態......或者至少(不是最好的)使用鎖。

7

你有沒有考慮在java.util.concurrent使用併發集合?很難給出比這更好的建議,說實話......我們需要更多的細節。

需要注意的一點是,如果您在線程之間共享可變集合,並且暴露於大量代碼中的可變集合以至於您在迭代時不知道可能會改變它,那麼您可能想要考慮如果可能的話改變你的設計。不變的集合通常可以使事情保持清潔,有時(但並非總是)以犧牲一些性能爲代價。他們可能比較難以開始工作,但您可能會發現事後更容易推理您的代碼。

+0

在大多數情況下,無法更改列表或地圖的類型,因爲它是一個參數。 – Horcrux7 2011-01-11 08:58:22

相關問題