我使用迭代器来循环集合,如下所示:
Iterator<Entity> entityItr = entityList.iterator();
while (entityItr.hasNext())
{
Entity curr = entityItr.next();
for (Component c : curr.getComponents())
{
if (c instanceof PlayerControlled)
{
((PlayerControlled) c).pollKeyboard();
}
}
}
但是在下面的行中我得到一个 ConcurrentModificationException
Entity curr = entityItr.next();
当我没有改变任何东西时为什么会发生这种情况?
非常感谢
编辑-堆栈跟踪:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at cw.systems.Input.checkInputs(Input.java:31)
at cw.systems.Input.begin(Input.java:21)
at cw.misc.Game.render(Game.java:73)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:207)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)
您必须修改该列表:
- 在你的迭代器中
pollKeyboard
方法,不使用add
or remove
迭代器上的方法;或者
- 在另一个线程中
因此,您的异常是预期的行为。从the docs http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html,如果您有一个迭代列表的线程:
如果在创建迭代器后的任何时间对列表进行结构修改,除了通过迭代器自己的删除或添加方法之外的任何方式,迭代器将抛出 ConcurrentModificationException
如果多个线程同时使用该列表:
请注意,此实现不是同步的。如果多个线程同时访问一个ArrayList实例,并且至少有一个线程在结构上修改了列表,必须与外部同步
解决方案:
如果只有一个线程访问该列表,请确保使用entityItr.remove http://docs.oracle.com/javase/7/docs/api/java/util/ListIterator.html#remove() or add
修改列表的方法。
对于多线程情况,您可以使用Collections.synchronizedList http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#synchronizedList(java.util.List)如果您没有可用的锁定对象。
首先将单个中央引用存储到您的列表中:
entityList = Collections.synchronizedList(theOriginalArrayList);
然后访问它(与所有读者和作者):
synchronized (entityList) {
// Readers might do:
itr = entityList.iterator();
while (i.hasNext())
... do stuff ...
}
还有其他方法可以同步多线程访问,包括将列表复制到数组(在同步块内)并迭代它以进行读取,或者使用ReadWrite
锁。它们都取决于您的具体要求。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)