Java 为什么我在这个不可修改集上得到ConcurrentModificationException?
在for循环开始的那一行,我得到了一个java.util.ConcurrentModificationException(参见代码中的注释) 为什么我在这个不可修改集上得到ConcurrentModificationExceptionJava 为什么我在这个不可修改集上得到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
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替换我的树集集合。不需要不可修改的集合。谢谢。