2015-08-21 131 views
1

我有一個私有類變量,它被聲明爲ConcurrentModificationException的當迭代通過列表

private List<String> list= new ArrayList<String>(); 

我的應用程序拋出java.util.ConcurrentModificationException當多個線程試圖通過列表迭代

for (Iterator i = list.iterator(); i.hasNext();){ 
    System.out.println(i.next()+"\n"); 
} 

我期待建議通過最小的更改來避免此問題。這個類變量被這個類中的多個方法共享和使用。

回答

0

既然你已經有一個線索,該列表將被多個線程訪問,聲明一個線程安全List

List<String> list= Collections.synchronizedList(new ArrayList<String>()); 
+0

考慮的javadoc聽起來像OP需要使用synchronized關鍵字也明確地同步。所以只是改變這個變量來利用Collections.synchronizedList可能還不夠。 – KumarM

1

當你在一個Collection使用iterator,你必須使用iterator.remove()而不是Collection.remove()防止ConcurrentModificationException。但是,如果您有多個線程,則可能還需要使用Collections.syncrhonizedList()

從Oracle的Java文檔:

List list = Collections.synchronizedList(new ArrayList()); 
    ... 
synchronized (list) { 
    Iterator i = list.iterator(); // Must be in synchronized block 
    while (i.hasNext()) 
     foo(i.next()); 
} 
+0

謝謝你的回答,但我認爲我給了錯誤的方向。所以所需的場景是多個線程訪問這個類,每個線程都使用該列表來存儲和檢索他們自己的計算。目前私人列表 list = new ArrayList ();將列表放置在由多個線程共享的堆中。我希望每個線程都有自己的列表副本。但是,我們正在獲取當前實現的ConcurrentModificationException異常。 – enfany

+0

我不太明白你的意思是每個線程都有自己的副本。當一個線程存儲新的東西時應該在其他線程中更新? –

+0

每個線程都會在這個列表中存儲不同的結果(因爲每個線程都會調用此類中的另一個方法,它將再次使用新的ArrrayList對列表進行初始化)我們希望將此類變量設置爲每個線程本地,而不是跨多個線程共享。 – enfany

1

你可以試試CopyOnWriteList,JavaDoc中說:

此數組在迭代器的生存期內不會改變,所以干擾是不可能的,迭代器保證不會拋出ConcurrentModificationException。

List<String> list = new CopyOnWriteArrayList<>(); 
+0

如果大部分活動都是寫入,那麼我們是否有替代結構來確保線程安全以及避免併發修改異常? – enfany