zoukankan      html  css  js  c++  java
  • 集合类不安全

    在多线程的情况下使用ArrayList进行读写的时候会出现java.util.ConcurrentModificationException,称为并发修改异常。

    代码如下

    public class NotSafeDemo {
    
        public static void main(String[] args) {
            //new Vector
            //ArrayList<String> list = new ArrayList<String>();
            //List<String> list=Collections.synchronizedList(new ArrayList());
            //使用CopyOnWriteArrayList();
            CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
            
            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();
            }
        }

    导致ArrayList不安全的原因

      add是没有加锁的

    public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }

    解决方案: 

    1. 使用Vector(不建议)
    2. 使用Collections.synchronizedList(new ArrayList());
    3. 使用java.util.concurrent包下的CopyOnWriteArrayList;

    小总结:

    /*
         * 笔记
         * 写复制
         * CopyOnWrite容器即写复制容器。往一个容器添加元素的时候,不直接往当前容器Object[]添加,而是将当前容器Object[]进行copy,
         * 复制出一个新的容器Object[] newElements,然后新的容器Object[] newElements里添加元素,添加完元素之后
         * 再将原容器的引用指向新的容器 setArray(newElements);这样做的好处是可以对CopyOnWrite容器进行并发读写,
         * 而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器
          public boolean add(E e) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len + 1);
                newElements[len] = e;
                setArray(newElements);
                return true;
            } finally {
                lock.unlock();
            }
        }
         */

     同样的问题hashSet也是存在的

    代码

    HashSet<String> set = new HashSet<String>();
            
            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(); 
                
            }
    出现
    java.util.ConcurrentModificationException

    修改成

    //HashSet<String> set = new HashSet<String>();
            Set<String> set = new CopyOnWriteArraySet<String>();
            
            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(); 
                
            }

    hashSet底层是hashMap。hashmap的初始值为16.负载因子为0.75。高并发的的时候很少使用hashMap,多使用

    HashMap也是不安全的

    代码:

    //Map<String, String> map = Collections.synchronizedMap(new HashMap<>());//new HashMap<>();
            Map<String,String> map=new ConcurrentHashMap();
            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();
            }
  • 相关阅读:
    python中的各种排序
    python 实现求和、计数、最大最小值、平均值、中位数、标准偏差、百分比。
    python中的lambda
    python中有趣的函数
    python中的小技巧
    python 删除list中重复元素
    django-pagination的使用
    django-south
    ios复制到剪贴板
    iOS系统验证关闭
  • 原文地址:https://www.cnblogs.com/fengyangcai/p/12897790.html
Copyright © 2011-2022 走看看