显然,有两种方法可以使用Java的HashSet
API获取线程安全的Collections
实例。
答案 0 :(得分:23)
你可能想到的是
Set<Type> set = Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());
这支持并发更新和读取。它的迭代器不会抛出ConcurrentModicationException。在哪里
Set<Type> set = Collections.synchronizedSet(new HashSet<Type());
重量更轻,但一次只允许一个线程访问该组。你需要明确地锁定集合,如果你想要迭代它,你仍然可以获得CME,如果你不以安全的方式更新它(当迭代它时)
答案 1 :(得分:6)
第一个返回一个Set,它基本上具有与作为参数传递的映射相同的线程安全性和性能保证。如果映射不是线程安全的,则该集合也不是。您通常使用此方法从并发映射创建并发集,因为API中没有ConcurrentHashSet。
第二个返回给定集合的代理,该集合的所有方法都已同步。
答案 2 :(得分:2)
实际上,您可能会获得多个Set线程安全实现。
予。 Collections.synchronizedSet(新的HashSet
我不推荐这个解决方案。它本身是线程安全的,在并发环境中仍然必须小心使用。参见:
Stack stack = new SynchronizedArrayStack(new ArrayStack());
...
// don't do this in a multi-threaded environment
if (!stack.isEmpty()) {
stack.pop(); // can throw IllegalStateException
}
因此,您必须使用客户端锁定:
synchronized(stack) {
if (!stack.isEmpty()) {
stack.pop();
}
}
II。 Set接口的第二个替代并发实现 - CopyOnWriteArraySet。但是,此解决方案不应在您期望进行许多搜索或插入的上下文中使用。但是,迭代每个元素的成本比HashSet要快O(1),并且它有一个在某些应用程序中非常引人注目的优点。
III。最后一个使用CuncurrentHashMap的实现:
Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());
它使用java.util.concurrent.locks.Lock的实现。映射将自身划分为可以单独锁定的部分,从而提高了并发性。所以你应该在最后两个选项中进行选择。
Thera也是排序集必须的选项。我建议你阅读Java Generics and Collections
章11.5 Collections and Thread Safety
。
答案 3 :(得分:1)
你错了。 newSetFromMap()不提供线程安全性。再次检查Javadoc。
这两种方法的输入类型也有不同之处。
答案 4 :(得分:1)
Collections API将地图构造留给客户端,如下所示:
ConcurrentHashMap<String, Boolean> conMap = new ConcurrentHashMap<String, Boolean>();
Set<String> users = Collections.newSetFromMap(conMap);
System.out.println("Users: " + users);
users.add("Jon");//results in adding to the conMap instance
users.add("Tyron");
System.out.println("Users: " + users);
System.out.println("conMap = " + conMap);
添加到集合中也会添加到地图
用户:[Tyron,Jon] conMap = {Tyron = true,Jon = true}
conMap.put("Jubin", Boolean.FALSE);
System.out.println("Users: " + users);
System.out.println("conMap = " + conMap);
添加到地图也会导致添加到集
用户:[Tyron,Jubin,Jon] conMap = {Tyron = true,Jubin = false,Jon = true}
ConcurrentHashMap.newKeySet使用KeySetView
创建新的HashMapConcurrentHashMap.KeySetView<String, Boolean> keySetView = ConcurrentHashMap.newKeySet();
keySetView.add("Feba");
System.out.println("keySetView = " + keySetView);
System.out.println("keySetView.getMap() = " + keySetView.getMap());
keySetView = [Feba] keySetView.getMap()= {Feba = true}
keySetView.getMap().put("BeN",Boolean.TRUE);
System.out.println("keySetView = " + keySetView);
System.out.println("keySetView.getMap() = " + keySetView.getMap());
keySetView = [BeN,Feba] keySetView.getMap()= {BeN = true,Feba = true}