Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/235.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我在这个不可修改集上得到ConcurrentModificationException?_Java_Android_Concurrency - Fatal编程技术网

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

Java 为什么我在这个不可修改集上得到ConcurrentModificationException?,java,android,concurrency,Java,Android,Concurrency,在for循环开始的那一行,我得到了一个java.util.ConcurrentModificationException(参见代码中的注释) 为什么我在这个不可修改集上得到ConcurrentModificationException final Set<Port> portSet = Collections.unmodifiableSet(node.getOpenPorts()); if (!portSet.isEmpty()) { StringBuilder tmpSb

在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("  ");
    }
}
final Set portSet=Collections.unmodifiableSet(node.getOpenPorts());
如果(!portSet.isEmpty()){
StringBuilder tmpSb=新的StringBuilder();

对于(端口pp:portSet){//某些内容必须正在修改基础集;即
node.getOpenPorts()返回的集

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

    final Set<Port> portSet = new HashSet<>(node.getOpenPorts());
final Set portSet=new HashSet(node.getOpenPorts());
但正如一位评论员(@Slaw)所指出的,这只是将迭代移动到构造函数中,您仍然会得到CCME

唯一真正的解决办法是:

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

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

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


我从未见过这种情况,但我从谷歌那里得到了车祸报告


是。只有在打开端口列表更改时执行此代码时,才会出现问题。

一定有什么东西在修改基础集;即
节点.getOpenPorts()返回的集。

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

    final Set<Port> portSet = new HashSet<>(node.getOpenPorts());
final Set portSet=new HashSet(node.getOpenPorts());
但正如一位评论员(@Slaw)所指出的,这只是将迭代移动到构造函数中,您仍然会得到CCME

唯一真正的解决办法是:

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

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

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


我从未见过这种情况,但我从谷歌那里得到了车祸报告


是。只有在打开端口列表更改时执行此代码时才会出现问题。

节点返回的
集能否被其他代码修改(不一定是您自己的代码)?好的。我猜我对
集合的假设是错误的。不可修改的集合
制作集合的副本是错误的。我猜它只是包装并阻止添加/删除?是的,
集合。不可修改的xxx
方法都包装给定集合。这些包装将委托给基础集合进行读取操作,但抛出
不支持的运算符写入操作的ionException
。由
节点.getOpenPorts()返回的
集能否被其他代码(不一定是您自己的代码)修改?好的。我猜我对
集合的假设是错误的。不可修改的集合
制作集合的副本是错误的。我猜它只是包装并阻止添加/删除?是的,
集合。不可修改的xxx
方法都包装给定集合。这些包装将委托给基础集合进行读取操作,但抛出
不支持的运算符用于写操作的ionException
。这不就是将迭代移动到
HashSet
内部吗?基于OP的代码,复制的行为似乎同样可能抛出
ConcurrentModificationException
。我将此标记为答案,因为我需要用ConcurrentSkipListSet替换我的树集e> 集合。不可修改集
不需要。谢谢。这不就是将迭代移动到
哈希集
内部吗?基于OP的代码,复制行为似乎同样可能抛出一个
ConcurrentModificationException
。我将此标记为答案,因为我需要做的是用ConcurrentSkipList替换我的树集集合。不需要不可修改的集合。谢谢。