ConcurrentModificationException,需要澄清
以下样机代码在ConcurrentModificationException
结束,发生(根据我的理解),由于我正在迭代一套,我正在修改的事实。ConcurrentModificationException,需要澄清
Set<String> data = new HashSet<String>();
data.add("a=1");
data.add("b=2");
data.add("c=3");
data.add("d=4");
for (String s : data) {
data.remove(s);
}
但是,为什么到了?请帮忙澄清
您违反合同迭代器的。从ConcurrentModificationException
javadoc,
如果单个线程发出的方法调用序列 违反对象的合同,该对象可能抛出此 例外。例如,如果一个线程直接修改集合 而迭代器使用快速迭代器迭代该集合,则迭代器将抛出此异常。
你必须使用迭代器从一组
我认为OP在问为什么。 –
仅仅是因为要修改的集合(通过调用data.remove(s)
),异常被抛出删除元素同时遍历它。 Java集合通常要求在迭代它们的值时不能修改它们。
它不是一般允许一个线程修改集合,而另一个线程上进行迭代。一般来说,在这些情况下迭代的结果是不确定的。某些迭代器实现(包括由JRE提供的所有通用集合实现的实现)可能会选择在检测到此行为时抛出此异常。这样做的迭代器被称为快速迭代器,因为它们快速且干净地失败,而在将来未定的时间冒着任意的,非确定性的行为冒险。
这是因为编译器实际上插入了Iterator
,然后使用传统的for循环遍历元素。如果修改迭代器创建的Collection
,则会导致未确定的行为。为了防止这种情况,引发ConcurrentModificationException
。
也here参见:
项目7.迭代过程中不要修改该列表。虽然for-each语法不能直接访问由等价基本for循环使用的迭代器,但可以通过直接调用列表中的其他方法来修改列表。这样做会导致不确定的程序行为。特别是,如果编译器插入的对iterator()的调用返回一个快速失败的迭代器,则可能会抛出java.util.ConcurrentModificationException运行时异常。但是,这只能以尽力而为的方式完成,除非作为在发生异常时检测错误的手段,否则不能被依赖。
或在Language Specification中的每个循环的部分。
而这样做的原因是,快速失败优于“在未来某个未定的时间冒着任意的,非确定性行为的风险”。 (同一文件) –
@Kublai Khan,感谢您的阐述,但我故意忽略包括那部分,因为我包含的片段已经足够。 – mre
因为这是为什么我认为会有帮助的问题。 -shrug- –