我正在尝试设计一个将流程图转换为java或任何其他代码的软件。但是我反复得到ConcurrentModificationException .. 但我不能使用布尔值来阻止concurrentModification,因为访问链表发生在各个地方。
作为解决方案,我创建了以下适配器类。但是它也会从下一个方法抛出相同的异常。有没有其他解决方案或者是否可以,请告诉我如何修改我的代码...
非常感谢你......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;
}
}
答案 0 :(得分:8)
在遍历列表时通常抛出ConcurrentModificationException
,同时通常另一个线程甚至同一个循环尝试修改(添加/删除)列表的内容。
答案 1 :(得分:3)
为什么不使用 LinkedBlockingQueue ? http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html
顺便说一句,这与同步无关。像这样的代码:for(Value v : valuesList){
valueslist.add(new Value());
}
也会导致此异常。检查代码,以便在迭代时对列表进行可能的修改。
答案 2 :(得分:2)
使用synchronizedList或同步列表时,在迭代时仍需要在外部进行同步。
如果您使用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.
注意:如果您正在使用另一个线程的队列,我建议您使用ExecutorService,因为这会将Queue与ThreadPool结合起来,并且更容易使用“后台”线程。
答案 3 :(得分:1)
当您遍历列表并在循环体中向其添加元素时,会发生这种情况。您可以在使用迭代器的remove()
方法时安全地删除元素,但不能通过调用列表本身的任何remove()
方法来删除元素。
解决方案是在迭代之前复制列表:
List<T> copy = new ArrayList<T>( list );
for( T e : copy ) {
... you can now modify "list" safely ...
}
答案 4 :(得分:1)
Java集合是快速失败的,这意味着所有现有迭代器在修改基础集合时变为无效 - 同步修改不会阻止列表使所有迭代器无效。
作为一种解决方法,您可以创建列表的副本以迭代或推迟修改,直到迭代完成。要删除条目,您还可以使用iterator.remove()方法来保持迭代器本身有效。
答案 5 :(得分:0)
List<X> myList = ....
List<X> myThreadSafeList = synchronizedList(myList);
请注意JavaDoc中的以下语句:
当迭代时,用户必须手动同步返回的列表:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
答案 6 :(得分:0)
答案在这里:Why am I getting java.util.ConcurrentModificationException?给了我很多帮助。
我会将其复制并粘贴到此处,以防有人想要修复此错误:
当您遍历列表时,无法从中删除项目。这样做会导致异常。
执行:
int size = list.size();
for (int i = 0 ; i< size ; i++) {
list.add(0,"art");
list.remove(6);
System.out.println(list);
}