首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Collections.newSetFromMap(»ConcurrentHashMap«)与Collections.synchronizedSet(哈希集)

Collections.newSetFromMap(»ConcurrentHashMap«)与Collections.synchronizedSet(哈希集)
EN

Stack Overflow用户
提问于 2012-07-05 18:54:42
回答 5查看 11.7K关注 0票数 16

显然,使用Java的螺纹安全实用程序类获得HashSet实例有两种方法。

我问:

  • 它们有何不同?
  • 在什么情况下,哪一种比另一种更可取?
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-07-05 19:04:03

你可能在想的是

代码语言:javascript
复制
Set<Type> set = Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());

这支持并发更新和读取。它的迭代器不会抛出ConcurrentModicationException。何地as

代码语言:javascript
复制
Set<Type> set = Collections.synchronizedSet(new HashSet<Type());

重量较轻,但一次只允许一个线程访问该集。您需要显式地锁定集合,如果您想要对它进行迭代,如果不以安全的方式更新它,仍然可以获得CME (同时迭代它)。

票数 28
EN

Stack Overflow用户

发布于 2012-07-05 18:59:00

第一个返回的集合与作为参数传递的映射具有相同的线程安全和性能保证。如果映射不是线程安全的,那么集合也不会是线程安全的。您通常使用此方法从并发映射创建并发集,因为API中没有ConcurrentHashSet。

第二个方法将代理返回给给定的集合,该集合同步了它的所有方法。

票数 9
EN

Stack Overflow用户

发布于 2012-07-11 10:32:05

实际上,您可能会得到一些设置线程安全的实现。

I. Collections.synchronizedSet(新HashSet )

我不建议这个解决办法。它本身是线程安全的,在并发环境中仍然必须谨慎使用。请参见:

代码语言:javascript
复制
Stack stack = new SynchronizedArrayStack(new ArrayStack());
...
// don't do this in a multi-threaded environment
if (!stack.isEmpty()) {
  stack.pop();              // can throw IllegalStateException
}

因此,您必须使用客户端锁定:

代码语言:javascript
复制
synchronized(stack) {
  if (!stack.isEmpty()) {
    stack.pop();
  }
}

二、Set接口的第二种并行实现-- CopyOnWriteArraySet。但是,此解决方案不应在您期望进行许多搜索或插入的上下文中使用。但是迭代的每个元素比HashSet花费O(1)快,而且它有一个优点,在某些应用程序中是非常引人注目的。

最后一种方法使用CuncurrentHashMap的实现:

代码语言:javascript
复制
Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());

它使用java.util.concurrent.locks.Lock的实现。该映射将自己划分为可以单独锁定的部分,从而改进了并发性。所以你应该在最后两个选项中做出选择。

也是排序集冲击元素的选项。我建议你阅读Java Generics and Collections章节11.5 Collections and Thread Safety

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11350723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档