使用Iterator的ConcurrentModificationException [英] ConcurrentModificationException using Iterator

查看:107
本文介绍了使用Iterator的ConcurrentModificationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用迭代器循环遍历集合,如下所示:

I'm using an iterator to loop over a collection as follows:

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

However on the following line I get a ConcurrentModificationException

 Entity curr = entityItr.next();

为什么在我没有改变任何事情时会发生这种情况?

Why is this happening when I'm not altering anything?

非常感谢

编辑 - 堆栈跟踪:

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)


推荐答案

您必须修改列表:


  1. pollKeyboard 方法中的迭代器内,不使用在迭代器上添加 remove 方法;或者

  2. 在另一个帖子中

  1. inside your iterator in the pollKeyboard method, without using the add or remove methods on the iterator; or
  2. in another thread

因此,您的例外是预期的行为。从文档中,如果您有一个迭代列表的线程:

Therefore your exception is the expected behaviour. From the docs, if you have a single thread iterating the list:


如果在创建迭代器之后的任何时候对列表进行结构修改,除非通过迭代器自己进行删除或添加方法,迭代器将抛出一个ConcurrentModificationException

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

并且如果多个线程一次使用该列表:

and if multiple threads uses the list at one time:


请注意,此实现未同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,必须在外部同步



解决方案:



如果只有一个线程访问该列表,请确保使用 entityItr.remove 添加方法来修改列表。

Solution:

If only one thread accesses the list, make sure you use the entityItr.remove or add methods to modify the list.

对于多线程情况,你可以使用 Collections.synchronizedList 如果您没有可用的锁定对象。

For the multi-threaded case you can use Collections.synchronizedList if you do not have a locking object available.

首先将单个中央引用存储到您的列表中:

First store a single central reference to your list as:

entityList = Collections.synchronizedList(theOriginalArrayList);

然后访问它(所有读者和作者):

And then access it (with all readers and writers) as:

synchronized (entityList) {
  // Readers might do:
  itr = entityList.iterator();
  while (i.hasNext())
    ... do stuff ...
}

还有其他方法可以同步多线程访问,包括将列表复制到一个数组(在同步块内)并迭代它以进行读取,或者使用 ReadWrite 锁定。它们都取决于您的确切要求。

There are other ways to sync multi-threaded access, including copying the list to an array (inside a sync block) and iterating it for reading, or using a ReadWrite lock. They all depend on your exact requirement.

这篇关于使用Iterator的ConcurrentModificationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆