为什么我在此unmodifiableSet上收到ConcurrentModificationException?

时间:2018-11-11 01:54:21

标签: java android concurrency

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

为什么我在此unmodifiableable上收到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得到崩溃报告。

1 个答案:

答案 0 :(得分:3)

必须修改底层集合;即node.getOpenPorts()返回的集合。

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

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

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

唯一真正的解决方案是:

  • 更改节点类的实现,以将并发集合类用于端口列表,如果在迭代过程中对集合进行了更改,则不会抛出CCME。

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

  • 尝试/捕获代码,如果获得CCME,请重复操作


  

我从来没有亲眼目睹过,但是我从Google得到崩溃报告。

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