如何保证HashSet线程安全?

大家好,我是指北君。,线程安全的问题,真的算是老生常谈了。这几天看到一个 Ha%ignore_a_1%hSet 线程安全的骚操作,在这里分享给大家。 在本文中,我们将分享如何构造线程安全的HashSet的几种方法。,使用ConcurrentHashMap工厂方法构造线程安全的HashSet
,首先, 我们来看看_ConcurrentHashMap_暴露出来的静态方法 — newKeySet()。此方法返回一个Set的实例,等同于实现了 java.util.Set 接口,而且能够使用Set的一些常用操作,比如 add(), contains() 等。,举个例子:,这里返回的Set,其实有点类似于 HashSet,因为两者都是基于Hash算法实现的,另外线程同步逻辑带来的额外开销也很小,因为它最终还是 ConcurrentHashMap 的一部分。,不过,这个只能在 Java 8 以上版本才可以使用,我想大部分公司应该至少 Java 8 了吧。直接拿来用就行。,现在,我们已经了解了可以用 ConcurrentHashMap#newKeySet()构建类似于线程安全的HashSet,在 ConcurrentHashMap 其实被定义为 KeySetView。ConcurrentHashMap 其实还有两个实例方法可以用于构建 KeySetView, 一个是 keySet() 另外一个就是keySet(defaultValue), 我这里就简写一下了, 大家可以在IDE中直接打出来看看。,这两个方法都可以创建KeySetView的实例,KeySetView 与 Map 是一个连接的关系。 我们每次向Map中添加新的键值对的时候,Set中的数据也在相应的添加,我们通过几个例子来看看这两种方法有哪些区别。,keySet() 方法 和 keySet(defaultValue) ,最大的区别就是不能直接往Set中添加数据。直接添加的话,会抛出 UnsupportedOperationException 异常,源码中的定义如下。,所以我们只能通过如下的方式使用。,输出结果如下。,keySet(defaultValue) ,由于有设置默认的value,可以在添加的时候不会报错,JDK 源码纵定义如下:,所以我们可以通过如下的方式使用。,输出结果如下:,java.util.Collections 中有一个线程同步的方法可以用于创建,示例代码如下。,这个方法的性能并没有ConcurrentHashMap的那个效率高,由于使用了同步锁,增加了一些额外的开销。,用CopyOnWriteArraySet 创建线程安全的 set 也是非常简单的。示例代码如下,这个方法从性能的角度上来看,也不是很理想,CopyOnWriteArraySet 背后的实现是CopyOnWriteArrayList, 最终使用了数组来存储数据,也就意味着 contains() 或者 remove() 操作,具有 O(n) 的复杂度,而使用HashMap 复杂度为 O(1) 。,建议使用此实现时,设置大小通常保持较小,只读操作占大多数。,在本文中,我们看到了不同的创建线程安全的Set的方式,也比较了他们之间的差异性。 所以大家以后使用的时候,可以考虑使用ConcurrentHashMap创建的Set。

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/18842.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年3月5日 上午12:00
下一篇 2023年3月7日 下午10:34