zoukankan      html  css  js  c++  java
  • 验证HashSet和HashMap不是线程安全

    JAVA集合类:
    java.util包下的HashSet和HashMap类不是线程安全的,
    java.util.concurrent包下的ConcurrentHashMap类是线程安全的。

    写2个测试类来验证下:

    package com.cdfive.learn.thread;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * 验证HashSet不是线程安全
     *
     * @author cdfive
     * @date 2019-02-11
     */
    public class HashSetTest {
        public static void main(String[] args) {
            final Set<Integer> set = new HashSet<>();// 结果可能大于1000
    //        final Set<Integer> set = Collections.synchronizedSet(new HashSet<>());// 结果等于1000
    //        final Set<Integer> set = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());// 结果等于1000
    
            // 往set写入1-1000
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    for (int i = 1; i <= 1000; i++) {
                        set.add(i);
                    }
                }
            };
    
            int threadNum = 10;// 线程数
            List<Thread> threadList = new ArrayList<>();
            for (int i = 0; i < threadNum; i++) {
                Thread thread = new Thread(runnable);
                threadList.add(thread);
                thread.start();
            }
    
            // 主线程等待子线程执行完成
            for (Thread thread : threadList) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            System.out.println(set.size());// 结果可能大于1000
        }
    }
    
    package com.cdfive.learn.thread;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * 验证HashMap不是线程安全
     *
     * @author cdfive
     * @date 2019-02-11
     */
    public class HashMapTest {
        public static void main(String[] args) {
            final Map<Integer, Integer> map = new HashMap<>();// 结果可能大于1000
    //        final Map<Integer, Integer> map = Collections.synchronizedMap(new HashMap<>());// 结果等于1000
    //        final Map<Integer, Integer> map = new ConcurrentHashMap<>();// 结果等于1000
    
            // 往map写入1-1000, key和value相同
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    for (int i = 1; i <= 1000; i++) {
                        map.put(i, i);
                    }
                }
            };
    
            int threadNum = 2;// 线程数
            List<Thread> threadList = new ArrayList<>();
            for (int i = 0; i < threadNum; i++) {
                Thread thread = new Thread(runnable);
                threadList.add(thread);
                thread.start();
            }
    
            // 主线程等待子线程执行完成
            for (Thread thread : threadList) {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            System.out.println(map.size());// 结果可能大于1000
        }
    }
    

    如果需要保证线程安全的场景:
    1.将HashSet或HashMap转换为线程安全,使用Collections.synchronizedSet或Collections.synchronizedMap方法;
    2.使用Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>())或使用java.util.concurrent包下的ConcurrentHashMap;
    3.仍然使用HashSet或HashMap,使用时手动进行加锁或同步;// 注意加锁粒度,尽可能保证性能

    在项目中根据实际场景进行选择和应用。

  • 相关阅读:
    LeetCode之移除元素
    有被开心到hh(日常)
    交换排序
    插入排序
    顺序查找&折半查找
    C++之引用
    MySQL学习笔记
    C/C++程序编译过程
    计算机面试知识整合(更新中...)
    MFC之编辑框
  • 原文地址:https://www.cnblogs.com/cdfive2018/p/10361300.html
Copyright © 2011-2022 走看看