集合不安全之 ---> List

List : 在多线程操作List的时候,在一个线程里面add东西,list实际上的大小跟预计是不一样的

  public void demo1() {
        List<String> list = new ArrayList<>();
        Random random = new Random();

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                list.add(String.valueOf(random.nextInt()));
                System.out.println(list);
            }).start();
        }

        //出现异常:Exception in thread "Thread-0" java.util.ConcurrentModificationException
    }

解决方法:

  • - 使用Vector类,Vector线程安全,缺点效率不高。
  • - 使用Collections.synchronizedList()方法,参数为一个List对象
  • - 使用CopyOnWriteArrayList类

CopyOnWriteArrayList的底层 add() 方法的实现:

原理:写时进行复制

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();//返回object数组
        int len = elements.length; //得到原数组的长度
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;//进行下标赋值
        setArray(newElements);//进行数组赋值
        return true;
    } finally {
        lock.unlock();
    }
}


//setArray的源码

final void setArray(Object[] a) {
    array = a;
}
 

remove方法:

    public E remove(int index) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            E oldValue = get(elements, index);
            int numMoved = len - index - 1;  //得到数组的整体之后的长度
            if (numMoved == 0)
                setArray(Arrays.copyOf(elements, len - 1));
            else {
                Object[] newElements = new Object[len - 1];
                System.arraycopy(elements, 0, newElements, 0, index);
                System.arraycopy(elements, index + 1, newElements, index,
                                 numMoved);
                setArray(newElements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }
原文地址:https://www.cnblogs.com/cb1186512739/p/12736255.html