为什么java concurrentmodificationexception会影响arraylists而不影响标准数组?

时间:2014-06-14 10:51:12

标签: java concurrentmodification

我前段时间看到一篇博客说如果你遇到concurrentmodificationexception问题,请将arraylist转换为常规数组[],你就没事了。但它没有解释。

为什么会这样?

2 个答案:

答案 0 :(得分:2)

addremove来自ArrayList的元素时,您正在更改其结构。这将使在此更改之前初始化的任何iterator无效。

另一方面,

数组没有真正的迭代器。 myArray[i] = myValue只是一个赋值 - 它对数组的结构没有任何作用,并且是原子的,就像任何其他赋值一样。

答案 1 :(得分:1)

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

请注意,此异常并不表示该对象已被其他线程同时修改。即使一个线程违反了对象的合同,也会抛出异常。

在Java中,尝试修改Iterator外部的Collections对象(ex, java.util.List)时可能会发生ConcurrentModificationException。文档指出线程是可能的原因,但即使进行单线程编程也可以获得此异常。

以下代码抛出ConcurrentModificationException,尽管在单个线程中执行。

List<String> mylist = new ArrayList<String>();
mylist.add("one");
Iterator<String> iterator = mylist.iterator();
while( iterator.hasNext() ) {
  iterator.next();
  mylist.remove(0);  // throws the exception
}

对mylist的remove()调用会干扰迭代器处理。在迭代时删除项目的正确方法是使用java.util.Iterator的{​​{1}}方法(这与remove()不同。

如果您维护一个应用程序并看到此异常,那么该错误很可能不像前面的代码块那样容易检测到。查找所有remove()调用并确保它们都在迭代器外部调用(如带索引的for循环)或迭代器java.util.List.remove(int))

(using iterator.remove()).

相关错误是IllegalStateException。如果在remove()之后没有推进迭代器,则会发生这种情况。

IllegalStateException

保持迭代器指针最新,一次使用iterator.next(); iterator.remove(); iterator.remove(); // will throw the error 操作一个元素;这来自Here.