1

我正在尝试编写一个游戏引擎,其中一个精灵列表用于保存所有精灵(列表列表让我以合理的方式对精灵进行排序)。问题是,我需要反复添加和删除精灵,这很快就违反了快速失败的迭代器,给了我一个并发修改异常。我可以在一个列表上有多个迭代器,这会阻止异常吗?如果做不到这一点,有没有办法“释放”列表的迭代器,以便列表不再检查修改?

4

2 回答 2

2

如果您想迭代列表的内容,因为它们在特定时间存在,而与迭代过程中发生的任何修改无关,您应该简单地制作一个副本并迭代该副本。

从性能的角度来看,这听起来可能很可怕,但我鼓励您尝试一下,并且仅CopyOnWriteArrayList在分析实际上表明创建副本是您完成的应用程序中的热点时才考虑替代方案(例如 )。垃圾收集器非常擅长使像这些副本这样的短期对象表现得非常好。

于 2012-08-30T02:19:50.690 回答
1

我可以在一个列表上有多个迭代器,这会阻止异常吗?

是的,你可以,不,它不会。(迭代器检查列表的状态以确定是否发生了并发修改。)

如果做不到这一点,有没有办法“释放”列表的迭代器,以便列表不再检查修改?

不,至少没有标准列表类。这将是一个坏主意,因为它可能会导致故障快速迭代器旨在避免的那种异常和数据损坏。(您是否希望您的应用程序因 ConcurrentModificationException 而失败,或者偶尔因随机数据结构损坏和/或奇怪的异常而失败?)

我认为您需要查看迭代器允许并发修改的替代 List 实现类。根据您的应用程序使用列表的方式,可能性包括:

  • CopyOnWriteArrayList这具有完整的列表语义,但写入操作往往有点昂贵。

  • ConcurrentLinkedDeque这是您在列表中期望的大部分操作(但不是位置插入或删除),并且写入操作更便宜。

在这两种情况下,迭代器都对迭代是否会看到所有元素提供较弱的保证。您需要仔细阅读相应的 javadocs 以确保语义合适。

除了一些历史例外,其中的集合类型java.util不是为并发/多线程用例设计的。如果您的应用程序需要由多个线程访问的集合类型,则需要查看java.util.concurrent包中的实现。

于 2012-08-30T01:57:42.040 回答