当前位置: 首页 > 面试题库 >

什么时候CopyOnWriteArraySet对实现线程安全的HashSet有用?

东方飞捷
2023-03-14
问题内容

Java,没有线程安全版本的HashMap命名的ConcurrentHashMap和线程安全版本TreeMap的命名ConcurrentSkipListMap,但没有ConcurrentHashSet对HashSet的。

相反,通常有4种使用线程安全的方法Set

  1. Set<String> mySet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
  2. Set<String> s = Collections.synchronizedSet(new HashSet<String>());
  3. ConcurrentSkipListSet<E>
  4. CopyOnWriteArraySet<E>

1所使用keySet()ConcurrentHashMap同时实现Set和线程安全的。

2使用synchronized方式,似乎不推荐这种方式。

3是基于ConcurrentSkipListMap并被广泛使用的。

4是基于CopyOnWriteArrayList的,因此它具有的相同基本属性CopyOnWriteArrayList。以下是从CopyOnWriteArraySet文档中选择的内容:http
:
//docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArraySet.html

  • 它最适合于集大小通常较小的应用,只读操作远远多于可变操作,并且您需要防止遍历期间线程之间的干扰。
  • 这是线程安全的。
  • 可变操作(添加,设置,删除等)非常昂贵,因为它们通常需要复制整个基础数组。
  • 迭代器不支持可变删除操作。
  • 通过迭代器进行遍历的速度很快,并且不会遇到其他线程的干扰。
  • 迭代器在构造迭代器时依赖于数组的不变快照。

由于通常使用1和3,为什么CopyOnWriteArraySet存在?什么时候CopyOnWriteArraySet有用?

补充:
CopyOnWriteArraySet基于CopyOnWriteArrayList,数据结构中的contains运算List为O(n),而Set数据结构用于高性能contains运算,有人可以解释吗?


问题答案:

当您有少量的线程安全集合元素时,此功能很有用。

一个示例是一组侦听器。您需要确保唯一性并有效地遍历它们。

BTW CopyOnWriteArraySet在每个引用的基础上具有最低的开销。大小可能只有其他集合的1/6。如果您有很多,这特别有用。

虽然Set数据结构是为了高性能而包含操作,但是有人可以解释吗?

就内存而言,COWAS效率contains更高,对于小型集合,COWAS的速度比其他方法要快。什么是“高性能”取决于使用情况。



 类似资料:
  • 简介 我们知道,JDK提供了线程安全的HashMap:ConcurrentHashMap,但是没有提供对应的ConcurrentHashSet,Hutool借助ConcurrentHashMap封装了线程安全的ConcurrentHashSet。 使用 与普通的HashSet使用一致: Set<String> set = new ConcurrentHashSet<>(); set.add("a"

  • 问题内容: 我知道Deamon是后台线程。我们可以通过调用创建自己的守护程序线程。 我的问题是:为什么以及何时需要将我们的线程创建为守护程序线程? 问题答案: 当所有正在运行的线程都是守护程序线程时,JVM将退出。因此,想象一下您正在编写一个简单的游戏,其中您的主要方法一直循环直到您决定退出为止。想象一下,在游戏开始时,您启动了一个线程,该线程将不断轮询某些网站以触发警报。当您决定结束游戏时,您希

  • 问题内容: 就像标题所说,我想使用Guava Collections获得线程安全的HashSet。 有空吗? 问题答案: 这是正确的答案,使用来自Guava的Sets类。无论如何,@ crhis的答案是好的。

  • 问题内容: 如果我通过Collections.unmodifiableSet()运行HashSet的实例后,它是否是线程安全的? 我问这个问题是因为Set文档指出不是,但是我只执行读取操作。 问题答案: 从Javadoc: 请注意,此实现未同步。如果多个线程同时访问哈希集,并且至少有一个线程修改了哈希集,则必须在外部对其进行同步 阅读不会修改一组,因此您没问题。

  • 问题内容: 因此,我对Node.js的工作方式有所了解:它具有一个侦听器线程,该线程接收事件,然后将其委托给工作池。工作线程一旦完成工作,便会通知侦听器,然后侦听器将响应返回给调用者。 我的问题是:如果我在Node.js中建立一个HTTP服务器,并在我的一个路由路径事件(例如“ / test / sleep”)中调用sleep,那么整个系统就会停顿下来。甚至是单个侦听器线程。但是我的理解是这段代码

  • 我看到了不同的PHP二进制文件,比如非线程或线程安全? 这是什么意思? 这些软件包之间有什么区别?