Java:迭代列表时的ConcurrentModificationException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6596673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java : ConcurrentModificationException while iterating over list
提问by Vinoth Kumar C M
When I execute the following code, I get ConcurrentModificationException
当我执行以下代码时,我得到 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();
}
Why am I getting the exception, even though I am using Collections.synchronizedList?
为什么我会收到异常,即使我使用的是 Collections.synchronizedList?
When I change myCollection to
当我将 myCollection 更改为
ConcurrentLinkedQueue<String> myCollection = new ConcurrentLinkedQueue<String>();
I don't get that exception.
我不明白这个例外。
How is ConcurrentLinkedQueue in java.util.concurrent different from Collections.synchronizedList ?
java.util.concurrent 中的 ConcurrentLinkedQueue 与 Collections.synchronizedList 有何不同?
回答by Andreas Dolk
A synchronizedList will does not provide a new implementation of Iterator
. It will use the implementation of the synchronizedlist. The implementationof iterator()
is:
一个同步列表将不会提供新的实现Iterator
。它将使用同步列表的实现。该执行的iterator()
就是:
public Iterator<E> iterator() {
return c.iterator(); // Must be manually synched by user!
}
From ArrayList
:
来自ArrayList
:
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间以任何方式修改列表结构,除了通过迭代器自己的 remove 或 add 方法,迭代器将抛出
ConcurrentModificationException
From ConcurrentLinkedQueue#iterator
:
来自ConcurrentLinkedQueue#iterator
:
Returns an iterator over the elements in this queue in proper sequence. The returned iterator is a "weakly consistent"iterator that will never throw
ConcurrentModificationException
, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.
以适当的顺序返回此队列中元素的迭代器。返回的迭代器是一个“弱一致性”迭代器,它永远不会 throw
ConcurrentModificationException
,并保证遍历在构造迭代器时存在的元素,并且可能(但不保证)反映构造之后的任何修改。
The iterators returned by the two collections are different by design.
这两个集合返回的迭代器在设计上是不同的。
回答by unbeli
don't do
不要做
myCollection.remove(myObject);
do
做
it.remove();
There is no need for synchronization or concurrent collection
不需要同步或并发收集
回答by Jason S
How is ConcurrentLinkedQueue in java.util.concurrent different from Collections.synchronizedList?
java.util.concurrent 中的 ConcurrentLinkedQueue 与 Collections.synchronizedList 有何不同?
They have different implementations, and therefore may choose whether to throw ConcurrentModificationException, or to handle the situation you describe gracefully. Evidently CLQ handles gracefully, and ArrayList wrapped by Collections.synchronizedList (my guess is the behavior is ArrayList's, not the wrapper's) does not.
它们有不同的实现,因此可以选择是抛出 ConcurrentModificationException 还是优雅地处理您描述的情况。显然 CLQ 处理得体,而由 Collections.synchronizedList 包装的 ArrayList(我的猜测是行为是 ArrayList 的,而不是包装器的)没有。
As @unbeli says, remove through the iterator, not the collection while iterating.
正如@unbeli 所说,通过迭代器删除,而不是在迭代时删除集合。