【问题标题】:What is the java provided class for ConcurrentModificationException in HashSet?java 为 HashSet 中的 ConcurrentModificationException 提供的类是什么?
【发布时间】:2015-09-04 09:48:55
【问题描述】:

如果我们在 HashSet 的 oracle 文档中看到,它指出在遍历 Set 时,如果我们尝试操作它,它会抛出 ConcurrentModificationException。可以理解。

这类似于 ArrayList 或 HashMap 的情况。但是如果我们看到,Java 提供了替代类,例如 CopyOnWriteArrayList 和 ConcurrentHashMap。

为什么没有这样的 HashSet 类来处理 ConcurrentModificationException?或者即使它存在,也请通知我。我不知道这样的课程

【问题讨论】:

标签: java multithreading collections synchronization


【解决方案1】:

如果您想要一个“ConcurrentHashSet”,其行为方式与ConcurrentHashMap 相同,您只需使用Collections.newSetFromMap() 并将ConcurrentHashMap 作为参数传递。

还有其他并发的Set 实现:例如ConcurrentSkipListSetCopyOnWriteArraySet

【讨论】:

  • 注意 Java-8 替代方案:ConcurrentHashMap.newKeySet()
  • 为什么传递给 newSetFromMap 方法的 Map 应该泛化为值的布尔值?
【解决方案2】:

TL;DR:ConcurrentModificationException 与线程无关!

您在java.util.concurrent 中提到的“并发”集合旨在为Collections.synchronizedXXX 提供快速且强大的替代方案。它们用于同时与多个线程一起使用。

另一方面,ConcurrentModificationException 发生在您更改集合的同时迭代它在同一个Thread中:

final List<String> list = ...
for(final String s : list) {
    list.remove(s);
}

此代码每次都会在第二次迭代中抛出ConcurrentModificationException。同时从多个线程访问非线程安全的Collection 是未定义行为,可能永远不会产生ConcurrentModificationException。或者它可能会着火。

为避免此类行为,请使用Iterator 并要求其修改Collection

final List<String> list = ...
final Iterator<String> iter = list.iterator();
while(iter.hashNext()) {
    final String s = iter.next();
    iter.remove();
}

要回答您完全不相关的问题,要创建线程安全的Set,只需使用以下代码:

final Set<String> threadSafe = Collections.newSetFromMap(new ConcurrentHashMap<>());

在添加Collections.newSetFromMap 之后,JDK 设计人员没有看到创建ConcurrentHashSet 类的意义。

总结

不要使用并发 Collection 来避免在单线程环境中不当使用 Collection。它充其量只会更慢,最坏的情况是使您的代码以意想不到的方式运行,因为迭代器为并发集合提供的一致性保证要宽松得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 2014-12-08
    • 2014-12-24
    • 2021-12-25
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    相关资源
    最近更新 更多