java LinkedList 中的 ConcurrentModificationException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12410093/
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
ConcurrentModificationException in LinkedList
提问by Sameera Kumarasingha
I am trying to designing a software that convert a flowchart into java or any other code. However I repeatedly getting the ConcurrentModificationException.. But I can't use a boolean to prevent concurrentModification, because access to the linked list happens in various places.
我正在尝试设计一个将流程图转换为 java 或任何其他代码的软件。但是我反复得到 ConcurrentModificationException .. 但是我不能使用布尔值来阻止 concurrentModification,因为对链表的访问发生在不同的地方。
So as a solution I created the below adapter class. However it also throws the same exception from next method. Are there any other solution or if can, plz let me know how to modify my codes...
因此,作为解决方案,我创建了以下适配器类。但是它也会从 next 方法抛出相同的异常。有没有其他解决方案,或者如果可以,请让我知道如何修改我的代码...
thank you very much...
非常感谢你...
import java.util.Iterator;
import java.util.LinkedList;
public class LinkedListAdapter<T> extends LinkedList<T>{
@Override
public boolean add(T t){
boolean b;
synchronized(this){
b = super.add(t);
}
return b;
}
@Override
public T remove(){
T t;
synchronized(this){
t = super.remove();
}
return t;
}
@Override
public Iterator<T> iterator(){
final LinkedListAdapter<T> adap = this;
return
new Iterator<T>(){
private Iterator<T> iter;
{
synchronized(adap){
iter = LinkedListAdapter.this.getIterator();
}
}
@Override
public boolean hasNext() {
boolean b;
synchronized(adap){
b = iter.hasNext();
}
return b;
}
@Override
public T next() {
T t;
synchronized(adap){
t = iter.next();
}
return t;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
protected Iterator<T> getIterator() {
Iterator<T> iter;
synchronized(this){
iter = super.iterator();
}
return iter;
}
}
回答by Dan D.
The ConcurrentModificationException
is usually thrown when iterating through the list and in the same time usually another thread or even the same loop tries to modify (add / remove) the contents of the list.
在ConcurrentModificationException
通常时抛出迭代通过列表,并在同一时间通常另一个线程,甚至同一回路试图修改(添加/删除)列表的内容。
回答by gilad hoch
why not use LinkedBlockingQueue? http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html
为什么不使用LinkedBlockingQueue?http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html
BTW, it's not neceserally have to do with synchronization. a code like this:
顺便说一句,它不一定与同步有关。像这样的代码:
for(Value v : valuesList){
valueslist.add(new Value());
}
would cause this exception as well. check your code for possible modifications of the list when it's being iterated over.
也会导致这个异常。检查您的代码是否在迭代时可能对列表进行了修改。
回答by Peter Lawrey
Using a synchronizedList or a synchronized list still has to be synchronised externally when iterating over it.
使用 synchronizedList 或同步列表在迭代时仍然必须在外部同步。
If you use ConcurrentLinkedQueue you don't have these issues.
如果您使用 ConcurrentLinkedQueue,则不会遇到这些问题。
Queue<Task> tasks = new ConcurrentLinkedQueue<Task>();
tasks.add(task); // thread safe
tasks.remove(task2); // thread safe
for(Task t: tasks) // can iterate without a CME.
Note: if you are using a queue with another thread I suggest you use an ExecutorService as this combines a Queue with a ThreadPool and make working with "background" thread much easier.
注意:如果您将队列与另一个线程一起使用,我建议您使用 ExecutorService,因为它将队列与 ThreadPool 相结合,并使“后台”线程的工作变得更加容易。
回答by josefx
Java collections are fail-fast, that means that all existing Iterators become invalid the moment the underlying collection is modified - synchronizing the modification does not stop the list from invalidating all iterators.
Java 集合是快速失败的,这意味着所有现有的迭代器在底层集合被修改的那一刻都变得无效 - 同步修改不会阻止列表使所有迭代器无效。
As a workaround you can create a copy of the list to iterate over or postpone modifications until the iteration is finished. To remove entries you can also use the iterator.remove() method which keeps the iterator itself valid.
作为解决方法,您可以创建列表的副本以迭代或推迟修改,直到迭代完成。要删除条目,您还可以使用 iterator.remove() 方法,该方法使迭代器本身有效。
回答by Aaron Digulla
This happens when you iterate over the list and add elements to it in the body of the loop. You can remove elements safely when you use the remove()
method of the iterator but not by calling any of the remove()
methods of the list itself.
当您遍历列表并在循环体中向其中添加元素时,就会发生这种情况。当您使用remove()
迭代器的方法而不是通过调用remove()
列表本身的任何方法时,您可以安全地删除元素。
The solution is to copy the list before you iterate over it:
解决方案是在迭代之前复制列表:
List<T> copy = new ArrayList<T>( list );
for( T e : copy ) {
... you can now modify "list" safely ...
}
回答by John B
List<X> myList = ....
List<X> myThreadSafeList = synchronizedList(myList);
Notice the following statement in the JavaDoc:
请注意 JavaDoc 中的以下语句:
It is imperative that the user manually synchronize on the returned list when iterating over it:
用户在迭代返回的列表时必须手动同步它:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
回答by Simon
The answer here: Why am I getting java.util.ConcurrentModificationException?helped me a lot.
答案在这里:为什么我会收到 java.util.ConcurrentModificationException?帮了我很多。
I will copy and paste it here in case anyone is looking to fix this error:
如果有人想要修复此错误,我会将其复制并粘贴到此处:
When you iterate through a list, you can't remove items from it. Doing so causes the exception.
当您遍历列表时,您无法从中删除项目。这样做会导致异常。
Do:
做:
int size = list.size();
for (int i = 0 ; i< size ; i++) {
list.add(0,"art");
list.remove(6);
System.out.println(list);
}