• ArrayList线程不安全解决办法


    先给出不安全的代码:

    public static void main(String[] args) {
        //List list = Collections.synchronizedList(new ArrayList<>());
        List list = new ArrayList();
        for(int i = 0; i < 30; i++){
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(Thread.currentThread().getName()+"\t"+list.toString());
                //System.out.println(list.toString());
            },"thread: "+i).start();
        }
    }

    运行完,控制台报错如下:

    报了并发修改异常。 

    给出解决办法:

    1.使用new Vector<>();进行替换(源码内部加锁synchronized线程安全,效率低)

    2.使用Collections工具类中的synchronizedList()方法,代码如下:

    List list = Collections.synchronizedList(new ArrayList<>());

    示例代码:

    public static void main(String[] args) {
        List list = Collections.synchronizedList(new ArrayList<>());
        //List list = new ArrayList();
        for(int i = 0; i < 30; i++){
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(Thread.currentThread().getName()+"\t"+list.toString());
                //System.out.println(list.toString());
            },"thread: "+i).start();
        }
    }

    同时Collections还提供了synchronizedMap()、synchronizedSet()等方法。

    3.使用JUC中的CopyOnWriteArrayList<>();

    new 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;
                // 1、将内容复制了一份
                Object[] newElements = Arrays.copyOf(elements, len + 1);
                // 2、写入新的内容
                newElements[len] = e;
                // 3、合并
                setArray(newElements);
                return true;
            } finally {
                lock.unlock();
            }
        }
     

  • 相关阅读:
    QT内存管理
    Redis主从模式(二)---拓扑结构及复制过程
    Node.js最新版黑马配套笔记
    Dockerfile 构建命令 及 dockerfile 设置默认时区
    SD-WAN在汽车零部件供应商中的成功案例分享
    软件项目管理 7.4.1.进度计划编排-超前与滞后方法
    如何解决香港服务器使用的常见问题
    Metasploit渗透测试框架
    【JMeter】JMeter压测过程中遇到Non HTTP response code错误解决方案
    Jenkins实战:docker compose 搭建Jenkins
  • 原文地址:https://blog.csdn.net/qq_36743013/article/details/126052057