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

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

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

时间: 2024-10-04 01:24:26

验证HashSet和HashMap不是线程安全的相关文章

你对hashset和hashmap了解多少?

首先,我们来看hashset. 他的构造函数:    public HashSet() {        map = new HashMap<>();    } 很惊讶吧.构造函数里面竟然有个hashmap! public boolean add(E e) {        return map.put(e, PRESENT)==null;    } 再看 add方法.里面有个present ,去看看present的定义: private static final Object PRESENT

Java集合Set、Map、HashSet、HashMap、TreeSet、TreeMap等

1.Set和Map的关系: Set代表一种集合元素无序.不可重复的集合,Map代表一种由多个key-value对组成的集合. Set的集合继承体系: Map关系集合 Map集合的key特征:所有key不能重复,key之间没有顺序.Map集合的所有key将具有set集合的特征. 对Set做改造可将Set改造成Map集合: 2.HashSet和HashMap的区别和联系:    对于HashSet,系统采用Hash算法决定集合元素的存储位置:对于HashMap,系统将value当成key的附属物,系

HashSet和HashMap的区别

HashSet和HashMap的区别.Java的HashSet类是由哈希表支持.它不保证 set 的迭代顺序:特别是它不保证该顺序恒久不变.此类允许使用 null 元素.HashSet类为基本操作提供了稳定性能,这些基本操作包括 add.remove.contains 和 size,假定哈希函数将这些元素正确地分布在桶中.. Java的HashMap和Hashtable都实现了Map接口.它们及其子类都采用Hash算法决定Map中key的存储. HashMap和Hashtable的主要区别有:线

HashMap与HashTable、HashSet与HashMap异同

1. HashMap与HashTable的区别: (1)HashMap允许将null作为一个entry的key或者value,而Hashtable不允许.当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null.因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断. (2)HashMap把Hashtable的contains方法去掉了,改成containsvalue和cont

ArrayList,HashSet以及HashMap(2019年10月23日)

包装类:对基本数据类型的包装,包装成引用数据类型(byte short int long float double boolean char) 基本数据类型对应的引用数据类型为:Byte Short Int Long Float Double Boolean  character 七种包装类(Character除外)都有接收字符串类型的构造方法 Boolean字符串参数 如果不是true,那么全是false 但是现在的jdk都有了自动装箱和自动拆箱的功能 集合:主要学习 ArrayList ,H

java数据结构之HashSet和HashMap(java核心卷Ⅰ读书笔记)

增加 删除 remove方法,可以删除指定的一个元素. 查找 ********************* **************************** HashSet既不可以用 0 1 2 3这种索引来确定元素的值,也不能用key来确定元素的值 ********************* HashSet就长这样的  ["aa" , "bb"] 长成这样的数据结构 ****************** HashMap长成这样的    {a=123  ,  

Java集合 -- HashSet 和 HashMap

HashSet 集合 HashMap 集合 HashSet集合 1.1 Set 接口的特点 Set体系的集合: A:存入集合的顺序和取出集合的顺序不一致 B:没有索引 C:存入集合的元素没有重复 1.2 HashSet 使用&唯一性原理 1.2.1 HashSet的使用 1.2.1.1 案例代码一: public class HashSetDemo2 { public static void main(String[] args) { //创建集合对象 HashSet<Student>

Java HashSet和HashMap源码剖析

转自: Java HashSet和HashMap源码剖析 总体介绍 之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说HashSet里面有一个HashMap(适配器模式).因此本文将重点分析HashMap. HashMap实现了Map接口,允许放入null元素,除该类未实现同步外,其余跟Hashtable大致相同,跟TreeMap不同,该容器不保证元素顺序,根据需要该容器可能会对元素重新哈希,元素的顺序也会被重新打散,

java基础之问题:请说出hashCode方法、equals方法、HashSet、HashMap之间的关系

①HashSet是采用HashMap来实现的:这个HashMap的key就是放进HashSet中的对象,value就是一个Object类型的对象 ②当调用HashSet的add方法时,实际上是想HashMap中增加了一行(key-value对),该行的key就是往HashSet增加的那个对象,该行的value就是一个Object类型的常量. ③HashMap底层采用数组来维护 ④调用增加的那个对象的hashCode方法,来得到一个hashCode,然后根据该值来计算出一个数组的下标索引(计算出数