0

我目前有一个简单的事件调度程序逻辑,它使用以下与侦听器列表配对的事件列表示例:

kotlin
val listenerMap: EnumMap<EventKey, MutableList<EventListener>> = EnumMap<EventKey::class.java)

它的作用如下:

  1. 对于每个EventKey表示应用程序内部的事件(可以是从NetworkDisconnectedto的任何IncorrectCredentials事件),如果该列表不为空,则该事件用于遍历其各自的事件侦听器列表,并将相应的事件调用分派给每个侦听器。

  2. listenerMap开始是空的,只有在添加了至少一个侦听器时才第一次填充每个侦听EventKeyEventKey,但是一旦在其中EventKey创建了条目,listenerMap它将不再被删除,只有它各自的侦听器列表将被改变(添加或删除的侦听器)。

  3. 我从不迭代列表,我只使用以下列表方法:List.addList.remove. 我知道在内部(android 源列表内部)可能会发生迭代,但那部分从未由我完成,也没有任何形式的迭代。我什至不使用List.contains.


我完全清楚,至少听众名单有风险ConcurrentModificationException,我已经能够触发。

我现在的问题是我很困惑哪种预防方法ConcurrentModificationException在确保它不会再次发生方面是最好的,并且在性能方面是最好的。

我有这个担心,因为这部分应用程序需要良好的性能。

以下是我在网上找到的与以下相关的解决方案的选项列表ConcurrentModificationException

  • 利用Collections.synchronizedMap(EnumMap<EventKey, MutableList<EventListener>>)
    • 当需要EnumMap<EventKey, MutableList<EventListener>>对 进行任何访问时,每次对listenerMapEnumMap
  • 利用Collections.synchronizedList(MutableList<EventListener>))
    • 读取列表或修改列表时,每次访问MutableList<EventListener>都通过此方法完成
  • 利用CopyOnWriteArrayList
    • 从我在网上找到的用户反馈来看,就性能而言,这似乎是一个非常昂贵的解决方案
  • 利用AtomicReference<MutableList<EventListener>>
    • 不太确定这个,但我看到了很多关于使用Atomic*代替使用的建议synchronized(*)
  • 使用synchronized(MutableList<EventListener>)/locks
    • 这是我想到的第一个,但我看到很多用户建议不要使用它,如果有其他更好的选择,比如使用Atomic*

现在我更倾向于使用Collections.synchronizedList,但我想知道是否有更好的方法来使用我所拥有的东西,只要ConcurrentModificationException安全包含,并且当前性能尽可能好。

此外,如果除了我上面列出的方法之外还有其他方法可以做到这一点,如果您认为它们优于那些方法,请随时提出建议。


笔记

请不要建议使用库来解决这个问题,这不是这个问题的目的。我知道周围有很多基于事件的调度库,这不是寻找最佳库的问题,而是寻找解决我问题的最佳方法。

4

0 回答 0