【问题标题】:Avoid ConcurrentModificationException using Iterator.next()使用 Iterator.next() 避免 ConcurrentModificationException
【发布时间】:2018-03-10 12:03:49
【问题描述】:

在我的 Android 应用中,我在地图上绘制一些航点时使用此代码

Iterator<Waypoint> iterator = waypoints.iterator();
while (iterator.hasNext()) {
   Waypoint w = iterator.next();
}

但是我收到了这个错误

致命异常:java.util.ConcurrentModificationException java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)

直接在我正在迭代的循环中修改列表。

但我可能会在另一个线程中修改列表,因为用户可以移动一些航点。并且航点的绘制可以在用户使用触摸屏移动航点的同时进行。

我能以某种方式避免该异常吗?

【问题讨论】:

  • 你不能把another reference 变成same list 吗?还是会conflict
  • 这行不通,因为底层列表是一样的。只是引用会不同。
  • 您的代码多久正确执行一次? ConcurrentModificationException 多久发生一次?如果是例如每秒执行几次的绘制例程我只会捕获异常并重新启动迭代。因为用户的行为通常非常缓慢,并且不会每秒增加十几个点。

标签: java android iterator concurrentmodification


【解决方案1】:

如果您想维护一个在多个线程中使用的List,最好使用并发列表,例如CopyOnWriteArrayList

在本地,您可以通过首先创建航点列表的副本并对其进行迭代来避免异常:

Iterator<Waypoint> iterator = new ArrayList<>(waypoints).iterator();
while (iterator.hasNext()) {
    handle(iterator.next());
}

【讨论】:

    【解决方案2】:

    数组列表提供的迭代器是fail-fast迭代器 - 这意味着一旦底层列表被修改它就会失败。

    避免异常的一种方法是将列表的快照放入另一个列表,然后对其进行迭代。

    Iterator<Waypoint> iterator = new ArrayList<>(waypoints).iterator();
    while (iterator.hasNext()) {
       Waypoint w = iterator.next();
    }
    

    另一种方法是使用实​​现故障安全迭代器的集合,例如CopyOnWriteArrayList

    【讨论】:

    • 在迭代之前每次都复制数组列表的成本很高,尤其是在 ConcurrentModificationException 的概率非常低的情况下。
    【解决方案3】:

    我看到了一些选项:

    一个。避免多线程。好吧,您不必完全避免多线程,只需访问数组即可。对数组的所有访问(甚至读取)都必须来自同一个线程。当然,繁重的计算可能发生在其他一些线程上。当您可以快速迭代时,这可能是一种合理的方法。

    b.锁定 ArrayList,即使是为了读取。这可能很棘手,因为过度锁定会导致死锁。

    c。使用数据副本。请记住,您只复制引用,但通常不必克隆所有对象。对于大型数据结构,可能值得考虑一些persistent data structure,它不需要复制所有数据。

    d。以某种方式处理 ConcurrentModificationException。也许重新开始计算。这在某些情况下可能很有用,但在复杂代码中可能会变得棘手。此外,在某些情况下,当访问多个共享数据结构时,您可能会遇到活锁——两个(或更多)线程相互重复导致 ConcurrentModificationException。

    编辑:对于某些方法(至少是 A),您可能会发现响应式编程很有用,因为这种编程风格减少了在主线程中花费的时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 2021-11-23
      • 2017-02-10
      • 2011-08-29
      • 2022-12-14
      • 2015-09-15
      相关资源
      最近更新 更多