如果我们在HashSet的oracle文档中看到,它声明在迭代Set时,如果我们尝试操作它,它会抛出ConcurrentModificationException。这是理解的。
这类似于ArrayList或HashMap的情况。但是如果我们看到,Java提供了备用类,例如CopyOnWriteArrayList和ConcurrentHashMap。
为什么HashSet没有任何解决ConcurrentModificationException的类?或者即使它存在,请提请我注意。我不知道这样的课程
答案 0 :(得分:1)
如果你想要" ConcurrentHashSet",其行为方式与ConcurrentHashMap
相同,你可以使用Collections.newSetFromMap()
并传递ConcurrentHashMap
作为参数。
还有其他并发Set
实施:例如ConcurrentSkipListSet
,CopyOnWriteArraySet
。
答案 1 :(得分:1)
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
的问题。它最多会变得更慢,最坏的情况会使你的代码以意想不到的方式运行,因为迭代器为并发集合提供的一致性保证更加轻松。