java - 为什么我在这个不可修改集上收到 ConcurrentModificationException?

标签 java android concurrency

我在 for 循环开始的行上收到 java.util.ConcurrentModificationException(请参阅代码中的注释)。

为什么我在这个不可修改的集上收到 ConcurrentModificationException?

final Set<Port> portSet = Collections.unmodifiableSet(node.getOpenPorts());
if (!portSet.isEmpty()) {
    StringBuilder tmpSb = new StringBuilder();
    for (Port pp : portSet) { // <------- exception happening here
        tmpSb.append(pp.getNum()).append("  ");
    }
}

我从未目睹过这种情况,但我收到了来自 Google 的崩溃报告。

最佳答案

一定有什么东西正在修改底层集合;即由 node.getOpenPorts() 返回的集合。

您可以复制它,而不是使用“不可修改的”包装器来包装集合。

    final Set<Port> portSet = new HashSet<>(node.getOpenPorts());

但正如评论者 (@Slaw) 指出的那样,这只是将迭代移至构造函数内,您仍然会获得 CCME。

唯一真正的解决方案是:

  • 更改节点类的实现,以对端口列表使用并发集类,如果集合在迭代时发生变化,该集类不会引发 CCME。

  • 更改节点类的实现以返回端口列表的副本。通过一些内部锁定来处理复制时更新竞争条件。

  • 在代码周围放置 try/catch,如果获得 CCME,请重复该操作

<小时/>

I've never witnessed this, but I'm getting crash reports from Google.

是的。仅当开放端口列表发生更改时执行此代码时,才会出现此问题。

关于java - 为什么我在这个不可修改集上收到 ConcurrentModificationException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53245185/

相关文章:

android - rxandroid 要求在 ui 线程上运行,即使它已在 AndroidSchedulers.mainThread() 上订阅

java - 使用 SwingWorker 更新 GUI

java - JBoss 无限制地忽略加密策略

java - WAR 安装错误的编码解决方案(Websphere Portal 6.0)?

android - 将谷歌广告添加到Android应用程序不显示广告

multithreading - 我如何将非静态数据发送到 Rust 中的线程,此示例是否需要它?

django - 将 gevent(或 eventlet)和 prefork worker 与 Celery 一起使用

java - 将 ListenableFuture 链转换为等效的 RxJava 结构

java - 如何在java类中使用logback为特定类和方法实现不同的记录器模式?

android - SQLIte 查询,选择等于的所有内容 - Android