码迷,mamicode.com
首页 > 编程语言 > 详细

验证HashSet和HashMap不是线程安全

时间:2019-02-12 00:30:25      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:exception   stat   exce   ++   date   boolean   override   ati   syn   

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,使用时手动进行加锁或同步;// 考虑到尽可能提升性能

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

验证HashSet和HashMap不是线程安全

标签:exception   stat   exce   ++   date   boolean   override   ati   syn   

原文地址:https://www.cnblogs.com/cdfive2018/p/10361300.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!