Hal*_*own 8 java collections multithreading
我正在使用即时模式GUI模式编写GUI应用程序,并且UI在独立于引擎的线程上运行,该引擎为应用程序的实际功能提供了动力。GUI线程最终会遍历引擎线程在概念上“拥有”的许多对象列表,并且这些列表很少发生更改。GUI线程是vsync的,这意味着它以大约60Hz的频率运行,而引擎线程以大约200Hz的频率运行。
有时,UI中的操作会更改引擎中集合的内容,并且我有一个消息传递系统将Runnables发布到引擎线程中以执行这些突变,以确保这些突变不会与引擎中发生的冲突发动机。这样,我可以确保引擎始终看到一致的数据视图,这对于我的应用程序非常重要。
但是,由于引擎负责所有数据突变,因此有时会发生这样的情况:引擎在迭代GUI时更改了集合的内容,并且由于这些集合是标准Java集合,因此可以预测并正确地抛出ConcurrentModificationException。我可以想到一些高级方法来解决此问题:
锁定会带来很大的性能损失,虽然GUI有时会在等待从引擎线程获取锁定时停滞是可以的,但对于引擎线程而言,以一致的速度运行非常重要,甚至R / W锁定会导致发动机螺纹失速。双缓冲具有显着的复杂性,因为GUI在每个帧上读取大量数据。
我为您提供所有这些背景知识,因为我知道选项3很难看,而且我的问题在某种意义上是“不合适的问题”。Javadoc ConcurrentModificationException甚至说:
请注意,不能保证快速故障行为,因为通常来说,在存在不同步的并发修改的情况下,不可能做出任何严格的保证。快速失败操作会尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的正确性是错误的:ConcurrentModificationException应该仅用于检测错误。
但!对于CME可能损坏的单个框架的GUI的正确性,我并不担心。我只关心下一帧会发生什么。这就引出了我的问题:从迭代器中抛出a之后,继续使用Java集合(我对ArrayListand 的答案最感兴趣HashMap)ConcurrentModificationException是否安全?这样做似乎是合乎逻辑的,但是我找不到找到说明在抛出CME之后对象仍将处于可用状态的文档。显然,迭代器在那时是敬酒的,但是我想吞下异常并继续使用该集合。
引用部分报价:
因此,这将是错误的编写一个程序,依赖于此异常的它的正确性:ConcurrentModificationException的应该仅用于检测bug。
结论:您的代码有错误,需要修复,因此集合处于什么状态都没有关系。
您永远都不会在有效代码中收到该错误。这是一个绝对不应该被抓住并采取行动的例外。
对于大多数馆藏,只要您只有一位作家,您也许还可以,但是并不能保证。如果您在HashMap上有多个编写器,那么您可能会得到一个损坏的地图,该地图的结构具有无限循环。
如果您只想获得一个锁(如果不使用ReentrantLock它的tryLock()话),则建议您使用一种有方法的方法来最大程度地减少阻塞。
将数据从一个线程传送到另一个线程的另一种方法是Queue修改任务,引擎在不繁忙时可以接管。这仅允许通过一个线程进行所有访问。
顺便说一句:锁定/解锁大约需要1微秒,除非您经常这样做,否则对您的影响不大。