当前位置: 首页 > 面试题库 >

使用Iterator的ConcurrentModificationException

伍胡媚
2023-03-14
问题内容

我使用迭代器遍历一个集合,如下所示:

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)

问题答案:

您必须修改列表之一:

  1. pollKeyboard方法中的迭代器内部,而无需使用迭代器上的addremove方法;要么
  2. 在另一个线程中

因此,您的例外是预期的行为。从该文档,如果你有一个线程遍历列表:

如果在创建迭代器后的任何时间对列表进行结构修改,则除了通过迭代器自己的remove或add方法以任何方式进行修改外,迭代器都会引发ConcurrentModificationException

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

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

解:

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

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

首先,将对列表的单个中央引用存储为:

entityList = Collections.synchronizedList(theOriginalArrayList);

然后以以下方式访问它(所有读者和作家):

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

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



 类似资料:
  • 通常,您需要遍历集合中的元素。 例如,您可能希望显示每个元素。 最简单的方法是使用迭代器,它是一个实现Iterator或ListIterator接口的对象。 Iterator使您可以循环访问集合,获取或删除元素。 ListIterator扩展Iterator以允许列表的双向遍历和元素的修改。 在通过迭代器访问集合之前,必须先获取一个集合。 每个集合类都提供了一个iterator()方法,该方法将迭

  • 我对Java还很陌生,今天我试图理解迭代器的使用。 所以我有几个问题: > 为什么我需要实现Iterable呢?它只提供了一个为集合创建新迭代器的方法,但如果我想获取所有元素,我也可以使用普通的或增强的for循环。我已经读过这个问题:可迭代接口用于什么?还有更多,但他们只是说它允许你遍历所有元素,这又回到了我的问题。 如果我实现了Iterable,我也应该实现迭代器吗 因为这一个实际上提供了可用于

  • 问题内容: 错误: 这是什么问题 问题答案: 某处正在修改。我怀疑它可能在此调用内发生: 编辑 基本上,发生的是通过 另一个 迭代器进行的递归修改。这使得外部迭代器的故障快速行为得以解决。 __

  • 迭代器设计模式属于行为设计模式类别。 开发人员几乎在每种编程语言中都遇到了迭代器模式。 此模式的使用方式有助于以顺序方式访问集合(类)的元素,而无需了解底层设计。 如何实现迭代器模式? 我们现在将看到如何实现迭代器模式。 import time def fib(): a, b = 0, 1 while True: yield b a, b = b, a + b

  • The Iterator object provides an API for iterating over a sequence. The purpose of the Iterator type is mainly to offer an agnostic way of iterating over a sequence -- either synchronous (i.e. with a w

  • 本文向大家介绍Java中Iterator和Spilled Iterator的区别。,包括了Java中Iterator和Spilled Iterator的区别。的使用技巧和注意事项,需要的朋友参考一下 迭代器和拆分迭代器这两个接口都用于迭代集合。 Java 8中引入了拆分迭代器来实现并行性。它可以拆分给定的元素集,并可以使用不同的独立线程并行执行操作。它可以并行地以及顺序地遍历元素。splitIte