集合类不安全

在多线程的情况下使用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();
        }
原文地址:https://www.cnblogs.com/fengyangcai/p/12897790.html