ArrayList、HashMap、HashSet是线程不安全的,高并发下如何解决?

1.故障现象 :ArrayList的add()方法并没有使用synchronized所以是线程不安全的,会造成java.util.ConcurrentmodificationException(并发修改异常)

2.导致原因:并发争抢修改导致

3.解决办法(以ArrayList为例,其他类似)

3.1使用Vector代替ArrayList,相比Vector的add()方法加了synchronized锁,保证了一致性,但是并发性下降了。
3.2 使用Collections工具类,List list = Collections.synchronizedList(new ArrayList<>()); 集合的接口是Collection,集合工具类是Collections
3.3使用juc(java.util.concurrent)包下的CopyOnWriteArrayList();写时复制(读写分离的思想),add()底层对数组增加一个容量Array.copyOf(element,length+1),添加add进的数据,把原来的数组失效,setArray()添加后的新数组。

代码实现

public class ArrayListDemo {
    public static void main(String[] args) {
//        List<String> list = Arrays.asList("a","b","c");
//
//        list.forEach(System.out::println);

        //Map<String,String> map = new HashMap<>();
        Map<String,String> map = new ConcurrentHashMap<>();
        //Map<String,String> map = Collections.synchronizedMap(new HashMap<>());
        //HashMap<String,String> map = new CopyOnWriteHashMap<>();
        for (int i=0; i < 30; i++){
            new Thread(()->{
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));
                System.out.println(map);
            },String.valueOf(i)).start();
        }

        Set<String> set = new HashSet<>();
        //HashSet底层是HashMap,
        // 但是为啥HashSet的add只要一个值,
        // 因为HashSet只有key变,value是一个PRESENT常量

        set.add("a");
        // Set<String> set1 = new ConcurrentHashSet<>();
        //Set<String> set = Collections.synchronizedSet(new HashSet<>());
        //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();
        }


        //List<String> list = new ArrayList<>();
        //List<String> list = new Vector<>();
        //List<String> list = Collections.synchronizedList(new ArrayList<>());
        List<String> list = new CopyOnWriteArrayList();
        for (int i=0; i < 30; i++){
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
        /**
         * 1.故障现象:java.util.ConcurrentModificationException
         *
         * 2.导致原因
         *
         * 3.解决方案(ArrayList、HashSet、HashMap一样)
         *   (1)使用vector()
         *   (2)使用collections工具类下的synchronizedList()
         *      List<String> list = new synchronizedList(new ArrarList());
         *      把线程不安全的ArrayList封装一层变成线程安全的。
         *   (3)JUC(java.util.concurrent)包下的CopyOnWriteArrayList()
         *
         * 4.优化建议(同样错误不犯第二次)
         *
         */

    }
}
发布了83 篇原创文章 · 获赞 61 · 访问量 9179

猜你喜欢

转载自blog.csdn.net/weixin_43736084/article/details/103810809