我正在尝试编写一个游戏引擎,其中使用精灵列表列表来保存所有精灵(列表列表让我以合理的方式命令精灵)。问题是,我需要反复添加和删除sprite,这很快就违反了快速失败的迭代器,给了我一个并发修改异常。我可以在列表上有多个迭代器,这会阻止异常吗?如果失败了,有没有办法'释放'列表的迭代器,以便列表不再检查修改?
答案 0 :(得分:2)
如果要迭代列表的内容(因为它们在特定时间存在),独立于迭代过程中发生的任何修改,您只需复制并迭代副本。
从性能的角度来看,这可能听起来很吓人,但我鼓励你尝试一下,只考虑其他选择(如CopyOnWriteArrayList
),如果分析确实表明创建副本是你的热点完成申请。垃圾收集器非常擅长制作像这些副本一样的短期对象。
答案 1 :(得分:1)
我可以在列表中使用多个迭代器,这会停止异常吗?
是的,你可以,不,不会。 (迭代器检查列表的状态以确定是否发生了并发修改。)
如果失败了,是否有办法'释放'列表的迭代器,以便列表不再检查修改?
没有,至少没有标准列表类。这将是一个糟糕的主意,因为它可能会导致失败快速迭代器旨在避免的那种异常和数据损坏。 (您希望您的应用程序在使用ConcurrentModificationException时可预测地失败,还是偶尔会因随机数据结构损坏和/或奇怪的异常而失败?)
我认为您需要查看替代List实现类,其中迭代器允许并发修改。根据您的应用程序使用列表的方式,可能包括:
CopyOnWriteArrayList
这有完整的列表语义,但写操作往往有点贵。
ConcurrentLinkedDeque
您在列表中预期的大多数操作(但不是位置插入或删除)和写入操作都会更便宜。
在这两种情况下,迭代器都提供了关于迭代是否会看到所有元素的较弱保证。您需要仔细阅读相应的javadoc,以确保语义合适。
有几个历史异常,java.util
中的集合类型不是为并发/多线程用例设计的。如果您的应用程序需要多个线程访问的集合类型,则需要查看java.util.concurrent
包中的实现。