在Java中,如何在单线程程序中抛出ConcurrentModificationException?

我正在阅读这个“ Freuqent Java并发问题 ”的问题,并且在谈论java.util.ConcurrentModificationException的答案时感到困惑。

我对答案的理解是,这可能发生在单线程程序中。 如何或什么条件导致以下代码抛出exception?

List list = new ArrayList(Arrays.asList("a", "b", "c")); for (String string : list) { list.remove(string); } 

此代码段将始终抛出ConcurrentModificationException

规则如下:使用迭代器(在使用for-each循环时发生)迭代时,您不能修改(添加或删除列表中的元素)。

但请注意,您可以使用Iterator.removeListIterator.add通过迭代器修改列表(因为它知道修改,并且可以将其考虑在内)。

来自文档:

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

这里并发一词指的是您遍历期间修改列表。

因为您要从列表中删除并同时使用迭代器对其进行迭代。

使用迭代器查看等效代码。

 import java.lang.*; import java.util.*; class Test{ public static void main(String[] argv){ List list = new ArrayList(Arrays.asList("a", "b", "c")); Iterator itr=list.iterator(); while(itr.hasNext()){ String a=itr.next(); list.remove(a); } } } 

正确的代码是

 import java.lang.*; import java.util.*; class Test{ public static void main(String[] argv){ List list = new ArrayList(Arrays.asList("a", "b", "c")); Iterator itr=list.iterator(); while(itr.hasNext()){ itr.remove(); } } } 

您在循环时更改列表。

这里ConcurrentModificationException与线程无关。

警告! 以下示例显示了在更改集合时如何使用集合可能会有危险。 这不是OP的确切情况(通过迭代器和更改循环)

我认为如果你使用一个带有这样的计数器的老式循环,会更容易想象它有什么问题:

 List list = new ArrayList(Arrays.asList("a", "b", "c")); for (int i = 0; i < list.size(); i++) { list.remove(i); //removes element at given index } 

现在,第一次i为0,第0个元素被删除。 第二次i是1,所以现在删除了第1个元素。 但是,在第一次移除之前,现在是第一个,曾经是第二个。 那么,曾经是第一,现在是第0,永远不会被删除。