ArrayList不安全的实例及解决方案

Posted 圣金巫灵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList不安全的实例及解决方案相关的知识,希望对你有一定的参考价值。

ArrayList线程不安全例子:

public class ListTest {
    public static void main(String[] args) {
        List<String> list = Collections.synchronizedList(new ArrayList<>());
//        List<String> list = new Vector<>();
//        List<String> list = Collections.synchronizedList(new ArrayList<>());
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                list.forEach(System.out::println);
            }).start();
        }
    }
}

报错ConcurrentModificationException:

 

 解决:

使用 Vector或者Collections.synchronizedList()方法

使用List<String> list = new CopyOnWriteArrayList<>();

来看看这个CopyOnWriteArrayList.这个是写时复制,读写分离的。

    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();
        }
    }
    final void setArray(Object[] a) {
        array = a;
    }

读的时候不加锁。

 

set同理。也有CopyOnWriteArraySet

public class ListTest {
    public static void main(String[] args) {
        Set<String> set = new CopyOnWriteArraySet<>();
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,8));
                set.forEach(System.out::println);
            }).start();
        }
    }
}

但是CopyOnWriteArraySet实际上是CopyOnWriteArrayList:

 

 

Map用ConcurrentHashMap, 数组+链表,如果长度大于8,链表成红黑树。

 

以上是关于ArrayList不安全的实例及解决方案的主要内容,如果未能解决你的问题,请参考以下文章

多线程下ArrayList类线程不安全的解决方法及原理

片段之间的静态 ArrayList

Python 自动化 - 浏览器chrome打开F12开发者工具自动Paused in debugger调试导致无法查看网站资源问题原因及解决方法,javascript反调试问题处理实例演示(代码片段

并发条件下SimpleDateFormat线程不安全及解决方案

CPNtools协议建模安全分析---实例变迁标记

ArrayListHashSet和HashMap线程不安全的解决办法