2011-07-06 24 views
8

當我執行下面的代碼,我得到ConcurrentModificationException的的Java:ConcurrentModificationException的同時遍歷列表

Collection<String> myCollection = Collections.synchronizedList(new ArrayList<String>(10)); 
    myCollection.add("123"); 
    myCollection.add("456"); 
    myCollection.add("789"); 
    for (Iterator it = myCollection.iterator(); it.hasNext();) { 
     String myObject = (String)it.next(); 
     System.out.println(myObject); 
     myCollection.remove(myObject); 
     //it.remove(); 
    } 

爲什麼會出現異常,即使我使用Collections.synchronizedList?

當我改變MyCollection的到

ConcurrentLinkedQueue<String> myCollection = new ConcurrentLinkedQueue<String>(); 

我沒有得到例外。

java.util.concurrent中的ConcurrentLinkedQueue如何與Collections.synchronizedList不同?

+0

可能的重複[遍歷集合,避免ConcurrentModificationException在循環中刪除時](http://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re) – Raedwald

回答

13

A synchronized列表將不會提供Iterator的新實現。它將使用執行同步的列表。的iterator()implementation是:

public Iterator<E> iterator() { 
    return c.iterator(); // Must be manually synched by user! 
} 

ArrayList

此類的iterator和listIterator方法返回的迭代器是快速失敗的:如果列表後隨時結構改性迭代器是以任何方式創建的,除了通過迭代器自己的刪除或添加方法外,迭代器將拋出一個ConcurrentModificationException

ConcurrentLinkedQueue#iterator

返回在此隊列中的元素以正確順序進行迭代器。返回的迭代器是一個「弱一致」迭代器,永遠不會拋出ConcurrentModificationException,並保證遍歷構造迭代器時存在的元素,並且可能(但不能保證)反映構造後的任何修改。

由兩個集合返回的迭代器是,設計不同

7

不做

myCollection.remove(myObject); 

it.remove(); 

無需同步或併發收集

+0

我的問題是,兩者有何不同? – vinoth

+0

@cmv,它與你的清單無關。它與你試圖在迭代它的同時修改集合有關。 ['Iterator.remove()'](http://download.oracle.com/javase/6/docs/api/java/util/Iterator.html#remove%28%29)可以讓你做到這一點。 – mre

+0

我的意思是,Collections.synchronizedList沒有照顧使操作原子..? – vinoth

2

是如何的ConcurrentLinkedQueue從集合不同的java.util.concurrent .synchronizedList?

它們有不同的實現,因此可以選擇是拋出ConcurrentModificationException還是處理你描述的情況。很明顯CLQ處理得很好,ArrayList包裝了Collections.synchronizedList(我的猜測是行爲是ArrayList的,而不是包裝的)不。

正如@unbeli所說,通過迭代器移除,而不是迭代時的集合。