Java Collections.newSetFromMap(»;ConcurrentHashMap«;)与Collections.synchronizedSet(»;HashSet«;)
显然,有两种方法可以使用Java的实用程序类获取实例Java Collections.newSetFromMap(»;ConcurrentHashMap«;)与Collections.synchronizedSet(»;HashSet«;),java,collections,concurrency,thread-safety,hashset,Java,Collections,Concurrency,Thread Safety,Hashset,显然,有两种方法可以使用Java的实用程序类获取实例 () () 我要求: 它们有何不同 在什么情况下,哪一个更受欢迎 你错了。newSetFromMap()不提供线程安全。再次检查Javadoc 还有一个小问题是这两个方法的输入类型不同。第一个方法返回的集合与作为参数传递的映射基本上具有相同的线程安全和性能保证。如果映射不是线程安全的,那么集合也不会是线程安全的。通常使用此方法从并发映射创建并发集,因为API中没有ConcurrentHashSet 第二个方法将代理返回给给定的集合,该集
- ()
- ()
- 它们有何不同
- 在什么情况下,哪一个更受欢迎
- 你错了。newSetFromMap()不提供线程安全。再次检查Javadoc
还有一个小问题是这两个方法的输入类型不同。第一个方法返回的集合与作为参数传递的映射基本上具有相同的线程安全和性能保证。如果映射不是线程安全的,那么集合也不会是线程安全的。通常使用此方法从并发映射创建并发集,因为API中没有ConcurrentHashSet
第二个方法将代理返回给给定的集合,该集合的所有方法都已同步 你可能想到的是
Set<Type> set = Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());
Set Set=Collections.newSetFromMap(新的ConcurrentHashMap());
这支持并发更新和读取。它的迭代器不会抛出ConcurrentModificationException。何处为
Set<Type> set = Collections.synchronizedSet(new HashSet<Type());
Set Set=Collections.synchronizedSet(新HashSet实际上,您可能会得到几个Set线程安全实现
I.Collections.synchronizedSet(新哈希集
我不推荐此解决方案。它本身是线程安全的,在并发环境中仍必须小心使用。请参阅:
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();
}
}
二、 Set接口的第二个可选并发实现—CopyOnWriteArraySet。但是,此解决方案不应用于需要大量搜索或插入的环境中。但是,迭代比HashSet每个元素的成本快0(1),并且它有一个优势,在某些应用程序中非常引人注目
三、 最后一个使用CuncurrentHashMap的实现:
Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());
Collections.newSetFromMap(新的ConcurrentHashMap());
它使用java.util.concurrent.locks.Lock的实现。映射将自身划分为可以单独锁定的部分,从而提高了并发性。因此,您应该在最后两个选项中进行选择
Thera也是排序集推进的选项。我建议您阅读Java泛型和集合
章节11.5集合和线程安全
集合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);
添加到地图也会导致添加到集合
用户:[泰龙、朱宾、乔恩]
conMap={Tyron=true,Jubin=false,Jon=true}
conMap.put("Jubin", Boolean.FALSE);
System.out.println("Users: " + users);
System.out.println("conMap = " + conMap);
ConcurrentHashMap.newKeySet使用KeySetView创建新的HashMap
ConcurrentHashMap.KeySetView<String, Boolean> keySetView = ConcurrentHashMap.newKeySet();
keySetView.add("Feba");
System.out.println("keySetView = " + keySetView);
System.out.println("keySetView.getMap() = " + keySetView.getMap());
keySetView=[BeN,Feba]
keySetView.getMap()={BeN=true,Feba=true}Duh,我的错。首先:我的意思是写Collections.newSetFromMap(»ConcurrentHashMap«)
-那么,现在的问题是:集合是从newSetFromMap(…)获得的吗
,使用java.util.concurrent
中的映射,仍然是线程安全的?@fbahr正如我所说的,检查Javadoc。它包含答案……并且Javadoc说“结果集显示与支持映射相同的顺序、并发性和性能特征”,因此如果将其与并发映射一起使用,该集也是一个并发集。很遗憾,投票的人回答不正确。大卫的问题是正确的。我认为你应该改写“只允许一条线阅读或写作”。
keySetView.getMap().put("BeN",Boolean.TRUE);
System.out.println("keySetView = " + keySetView);
System.out.println("keySetView.getMap() = " + keySetView.getMap());