Java:迭代列表时出现ConcurrentModificationException

Vin*_*C M 8 java collections

当我执行以下代码时,我得到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();
    }
Run Code Online (Sandbox Code Playgroud)

为什么我得到异常,即使我使用Collections.synchronizedList?

当我将myCollection更改为

  ConcurrentLinkedQueue<String> myCollection = new ConcurrentLinkedQueue<String>();
Run Code Online (Sandbox Code Playgroud)

我没有得到那个例外.

java.util.concurrent中的ConcurrentLinkedQueue与Collections.synchronizedList有何不同?

And*_*s_D 13

一个同步列表将不会提供新的实现Iterator.它将使用同步列表的实现.该执行iterator()就是:

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

来自ArrayList:

这个类的iterator和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过迭代器自己的remove或add方法之外,迭代器将抛出一个ConcurrentModificationException

来自ConcurrentLinkedQueue#iterator:

以适当的顺序返回此队列中元素的迭代器.返回的迭代器是一个"弱一致"的迭代器,它永远不会抛出ConcurrentModificationException,并保证遍历构造迭代器时存在的元素,并且可能(但不保证)反映构造之后的任何修改.

两个集合返回的迭代器在设计上不同的.


unb*_*eli 8

不要这样做

myCollection.remove(myObject); 
Run Code Online (Sandbox Code Playgroud)

it.remove();
Run Code Online (Sandbox Code Playgroud)

无需同步或并发收集

  • @cmv:是的,但是(与异常名称可能暗示的相反)这不是**多个线程同时执行某些操作的问题.这是**你的单线程**对列表进行结构操作(即添加/删除某些东西)的问题,而*同时*(即*并发*)在其上有一个活动的"迭代器".这个组合是未定义的*除非*你通过`Iterator`本身进行结构修改. (4认同)