使用迭代器时出现 java.util.LinkedList$ListItr.checkForComodification 异常?
Getting java.util.LinkedList$ListItr.checkForComodification exception while using iterators?
我正在使用 listIterator()
访问和删除 class 中的 LinkedList
中的项目,实现 Runnable
我也在某些方面修改此列表的值节目的其他部分同时进行。
我在这部分代码中使用 listIterator()
的地方,我从这个函数调用中得到 ConcurrentModificationException
:
java.util.LinkedList$ListItr.checkForComodification
为什么我会得到这个,我该如何预防?
@Override
public void run()
{
while(true)
{
itr = nodeAttributes.listIterator();
while (itr.hasNext())
{
System.out.println("enterred");
nodeAttribute nA = (nodeAttribute) itr.next();
//System.out.println("for");
if(!nA.isMoving && !nA.moveQueue.isEmpty())
{
if(animator != null)
animator.stop();
animator = (Animator) nA.moveQueue.poll();
//itr.remove();
animator.start();
nA.isMoving = true;
System.out.print( "animator");
}
}
System.out.println( "looping");
}
}
你的 post 没有问题,只有陈述。但是,您描述的是预期的行为。来自 the docs:
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.
因此,为了防止这种情况发生,您需要防止作者在 reader 迭代的同时进行修改。使用 Collections.synchronizedList
方法。所有访问(readers 和作者)都应遵循此模式:
// store a single synchronized list reference for all access to use
nodeAttributes = Collections.synchronizedList(theLinkedList);
然后所有 reader 和作者都应该使用 synchronized (list)
块。
// Readers might do:
synchronized (list) {
itr = nodeAttributes.listIterator();
while (i.hasNext())
... do stuff ...
}
那些不进行迭代操作的线程可以只使用 Collections.synchronizedList
的 return 对象上的 "atomic" 方法,例如 add
。这些方法在幕后使用同步块,因此它们只是一个 shorthand,当另一个在同步块中时它们仍会阻塞线程。
有很多方法可以处理并发 reader 和编写器。
- 一个是上面的,但它可能会在每个迭代器执行它的时候长时间锁定其他线程。
- 另一种是将列表复制到数组(在同步部分内),然后在锁外读取数组。
- 还有一个方法是使用
ReadWriteLock
.
还有更多选项,具体取决于您的具体用例。
我正在使用 listIterator()
访问和删除 class 中的 LinkedList
中的项目,实现 Runnable
我也在某些方面修改此列表的值节目的其他部分同时进行。
我在这部分代码中使用 listIterator()
的地方,我从这个函数调用中得到 ConcurrentModificationException
:
java.util.LinkedList$ListItr.checkForComodification
为什么我会得到这个,我该如何预防?
@Override
public void run()
{
while(true)
{
itr = nodeAttributes.listIterator();
while (itr.hasNext())
{
System.out.println("enterred");
nodeAttribute nA = (nodeAttribute) itr.next();
//System.out.println("for");
if(!nA.isMoving && !nA.moveQueue.isEmpty())
{
if(animator != null)
animator.stop();
animator = (Animator) nA.moveQueue.poll();
//itr.remove();
animator.start();
nA.isMoving = true;
System.out.print( "animator");
}
}
System.out.println( "looping");
}
}
你的 post 没有问题,只有陈述。但是,您描述的是预期的行为。来自 the docs:
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.
因此,为了防止这种情况发生,您需要防止作者在 reader 迭代的同时进行修改。使用 Collections.synchronizedList
方法。所有访问(readers 和作者)都应遵循此模式:
// store a single synchronized list reference for all access to use
nodeAttributes = Collections.synchronizedList(theLinkedList);
然后所有 reader 和作者都应该使用 synchronized (list)
块。
// Readers might do:
synchronized (list) {
itr = nodeAttributes.listIterator();
while (i.hasNext())
... do stuff ...
}
那些不进行迭代操作的线程可以只使用 Collections.synchronizedList
的 return 对象上的 "atomic" 方法,例如 add
。这些方法在幕后使用同步块,因此它们只是一个 shorthand,当另一个在同步块中时它们仍会阻塞线程。
有很多方法可以处理并发 reader 和编写器。
- 一个是上面的,但它可能会在每个迭代器执行它的时候长时间锁定其他线程。
- 另一种是将列表复制到数组(在同步部分内),然后在锁外读取数组。
- 还有一个方法是使用
ReadWriteLock
.
还有更多选项,具体取决于您的具体用例。