Java中的CopyOnWriteArrayList详解

 更新时间:2023年12月18日 10:38:12   作者:暴躁的程序猿啊  
这篇文章主要介绍了Java中的CopyOnWriteArrayList详解,ArrayList单线程下是安全的 但是多线程下存在不安全的问题,多线程下是不安全的,需要的朋友可以参考下

引入

ArrayList单线程下是安全的 但是多线程下存在不安全的问题

多线程下是不安全的

例如: 我们开启多个线程向arraylist添加数据

public class ListTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                list.add("a");
            System.out.println(list);
            }).start();
        }
    }
}

报出异常

在这里插入图片描述

解决这个问题我们可以使用集合工具类创建线程安全的ArrayList

  List<String> strings = Collections.synchronizedList(new ArrayList<String>());
    for (int i = 0; i < 101; i++) {
        new Thread(()->{
            strings.add("a");
            System.out.println(strings);
        }).start();
    }
}

在这里插入图片描述

但加入synchronized此时效率较低

所以我们可以使用juc包中的 CopyOnWriterArrayList

CopyOnWriterArrayList

CopyOnWriteArrayList (拷贝写数组) 是ArrayList线程安全的集合

其中所有可变操作(add、set等等)都是通过对底层数组进行一次新的复制来实现的。

适合场景:读多、写少的并发场景

cow思想

它不存在“扩容”的概念,每次写操作(add 、remove)都要copy一个副本,在副本的基础上修改后改变array引用,所以称为“CopyOnWrite”,因此在写操作是加锁,并且对整个list的copy操作时相当耗时的,过多的写操作不推荐使用该存储结构。

读取的方法没有加锁 写的时候才加锁 所以性能 比 vector高

我们可以从源码中看出

public E get(int index) {
    return get(getArray(), index);
}
final Object[] getArray() {
    return array;
}
private E get(Object[] a, int index) {
    return (E) a[index];
}

读操作并没有加锁 这也是效率高的原因

add源码

写操作加入了 lock锁

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();
    }
}

(注:新版本jdk1.8后改成了synchronized 因为新版本对synchronized进行了升级提升了效率)

使用示例:

public class ListTest {
    public static void main(String[] args) {
        List<String> list = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 101; i++) {
            new Thread(()->{
                list.add("a");
                System.out.println(list);
            }).start();
        }
    }
}

在这里插入图片描述

缺点:

内存问题:CopyOnWrite的写复制机制,在进行写操作的时候,内存里会同时驻存在两个对象的内存,旧的对象和新写入的对象(注意:在复制的时候只是复制容器里的引用,只是在写的时候会创建新对 象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存)。如果这些对象占用的内存比较大,比如说100M左右,那么再写入50M数据进去,内存就会占用150M,那么这个时候很有可能造成频繁的minor GC和major GC。

数据一致性问题:CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。

到此这篇关于Java中的CopyOnWriteArrayList详解的文章就介绍到这了,更多相关CopyOnWriteArrayList详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JAVA异常处理捕获与抛出原理解析

    JAVA异常处理捕获与抛出原理解析

    这篇文章主要介绍了JAVA异常处理捕获与抛出原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Java 守护线程_动力节点Java学院整理

    Java 守护线程_动力节点Java学院整理

    Java语言机制是构建在JVM的基础之上的,意思是Java平台把操作系统的底层给屏蔽起来,所以它可以在它自己的虚拟的平台里面构造出对自己有利的机制,而语言或者说平台的设计者多多少少是收到Unix思想的影响,而守护线程机制又是对JVM这样的平台凑合,于是守护线程应运而生
    2017-05-05
  • spring boot和spring cloud之间的版本关系

    spring boot和spring cloud之间的版本关系

    这篇文章主要介绍了spring boot和spring cloud之间的版本关系,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Java中的Semaphore信号量使用解析

    Java中的Semaphore信号量使用解析

    这篇文章主要介绍了Java中的Semaphore信号量使用解析,Semaphore 通常我们叫它信号量,可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源,需要的朋友可以参考下
    2023-11-11
  • SpringBoot如何整合redis实现过期key监听事件

    SpringBoot如何整合redis实现过期key监听事件

    这篇文章主要介绍了SpringBoot如何整合redis实现过期key监听事件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • 简单讲解在Java编程中实现设计模式中的单例模式结构

    简单讲解在Java编程中实现设计模式中的单例模式结构

    这篇文章主要介绍了简单讲解在Java编程中实现设计模式中的单例模式结构,设计模式是最基本直白简单的一种设计模式,需要的朋友可以参考下
    2016-04-04
  • Java 利用dom方式读取、创建xml详解及实例代码

    Java 利用dom方式读取、创建xml详解及实例代码

    这篇文章主要介绍了Java 利用dom方式读取、创建xml的相关资料,需要的朋友可以参考下
    2017-03-03
  • java中线程安全的list详细特性和用法

    java中线程安全的list详细特性和用法

    这篇文章主要给大家介绍了关于java中线程安全的list详细特性和用法的相关资料,Java中有多种线程安全的List,其中比较常用的有Vector、Collections.synchronizedList()和CopyOnWriteArrayList三种方式,需要的朋友可以参考下
    2024-03-03
  • springboot filter配置多个时,执行顺序问题

    springboot filter配置多个时,执行顺序问题

    这篇文章主要介绍了springboot filter配置多个时,执行顺序问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • java语言如何生成plist下载ipa文件

    java语言如何生成plist下载ipa文件

    这篇文章主要介绍了java语言如何生成plist下载ipa文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08

最新评论