随笔 - 1162  文章 - 0  评论 - 16  阅读 - 59万 

一、HasheSet 集合的不安全

  1、故障现象

复制代码
public class NotSafeSetDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();

        for (int i = 0; i < 30; i++) {
            new Thread(() -> {
                //向集合添加内容
                set.add(UUID.randomUUID().toString().substring(0, 8));
                //从集合获取内容
                System.out.println(set);
            }, String.valueOf(i)).start();
        }
    }
}
复制代码

  运行结果:

  

 

  2、分析

  (1)HashSet 是线程不安全的
  (2)HashSet 的底层是一个 HashMap(),但是这个 HashMap 的 value 永远是一个 Object 类型的常量(PRESENT),但HashSet的add是放一个值(调用map的PUT方法),而HashMap是放K、V键值对
复制代码
public HashSet() {
    map = new HashMap<>();
}
 
private static final Object PRESENT = new Object();
 
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}
复制代码

    因为底层使用的是 HashMap,而 HashMap 也是线程不安全的,并且 HashSet 的 add 方法也没有使用 synchronized 同步锁。

 

二、方案一

  1、使用 Collections 工具类

  Collections 工具类也提供了线程安全的 Set 集合。

  2、代码实现

复制代码
public class SafeSetDemo {

    public static void main(String[] args) {
        Set<String> set = Collections.synchronizedSet(new HashSet<>());

        for (int i = 0; i < 30; i++) {
            new Thread(() -> {
                //向集合添加内容
                set.add(UUID.randomUUID().toString().substring(0, 8));
                //从集合获取内容
                System.out.println(set);
            }, String.valueOf(i)).start();
        }
    }
}
复制代码

 

三、方案二

  1、使用 CopyOnWriteArraySet 

    原理同 CopyOnWriteArrayList。

  2、代码实现

复制代码
public class SafeSetDemo {

    public static void main(String[] args) {

        Set<String> set = new CopyOnWriteArraySet<>();
        for (int i = 0; i < 30; i++) {
            new Thread(() -> {
                //向集合添加内容
                set.add(UUID.randomUUID().toString().substring(0, 8));
                //从集合获取内容
                System.out.println(set);
            }, String.valueOf(i)).start();
        }
    }
}
复制代码

 

posted on   格物致知_Tony  阅读(1033)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
点击右上角即可分享
微信分享提示

目录导航