CopyOnWriteArrayList内存占用过多

CopyOnWriteArrayList原理,优缺点,使用场景 什么是CopyOnWrite容器   CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWri... 阅读详情

在这里插入图片描述

大家好,我是哪吒。

一、CopyOnWriteArrayList

CopyOnWriteArrayList是Java中的一个线程安全的ArrayList,它在每次修改时都会创建一个新的数组,并将原数组的引用赋值给新数组,从而达到线程安全的目的。由于它不断地创建新的数组并保留旧数组,因此内存占用可能会比较多。

CopyOnWriteArrayList具有以下特点:

  1. 线程安全:CopyOnWriteArrayList使用读写锁来确保并发访问时的线程安全性,因此可以在多线程环境下使用。
  2. 内存占用较高:由于它在每次修改操作时都会创建一个新的数组,并且会保留旧数组,因此内存占用可能会比较多。
  3. 适合读密集型应用:由于它只会在写操作时进行数组复制,因此对于读密集型的应用,使用CopyOnWriteArrayList可以减少锁竞争,提高并发性能。
  4. 不支持写操作:CopyOnWriteArrayList不支持add()和remove()方法,因为这些操作需要修改底层数组,从而导致所有线程都看到不一致的结果。因此,如果需要执行写操作,可以考虑使用其他的线程安全的数据结构,如Collections.synchronizedList()。

总之,CopyOnWriteArrayList适合读密集型应用,并且在写操作时需要注意内存占用问题。如果需要执行写操作,可以考虑使用其他的线程安全的数据结构。

二、CopyOnWriteArrayList的适用场景

CopyOnWriteArrayList主要适用于读多写少的场景,例如配置信息、缓存等数据的读取和更新操作。由于写操作的时候会进行数组复制,会消耗内存,如果原数组的内容比较多的情况下可能导致young gc或者full gc。因此,对于读操作非常频繁,而写操作相对较少的场景,使用CopyOnWriteArrayList可以提供较好的并发性能和线程安全性。

需要注意的是,CopyOnWriteArrayList在写操作中使用了ReentrantLock锁来保证线程安全,并替换原array属性;但是在读的时候直接读取array,可能会发生在写操作替换array前后,从而引发数据不一致的问题。因此,在使用CopyOnWriteArrayList时需要注意以下几点:

  1. 如果写操作未完成,那么直接读取原数组的数据是不一致的。
  2. 如果写操作完成,但是引用还未指向新数组,那么也是读取原数组数据是不一致的。
  3. 如果写操作完成,并且引用已经指向了新的数组,那么直接从新数组中读取数据是一致的。

总之,CopyOnWriteArrayList适用于读多写少且数据一致性要求较高的场景。

三、CopyOnWriteArrayList内存占用过多的解决方法

  1. 尽量避免在CopyOnWriteArrayList中进行频繁的修改操作。如果可能的话,可以尝试将这些修改操作集中在一起进行,从而减少数组的创建和销毁次数。
  2. 使用其他的线程安全的数据结构,比如Collections.synchronizedList()。这种数据结构使用的内存开销通常比CopyOnWriteArrayList小。
  3. 如果必须要使用CopyOnWriteArrayList,可以使用WeakReference来减少内存占用。具体来说,可以将数组元素使用WeakReference管理,当数组不再被引用时,垃圾回收器可以将其回收,从而释放内存。

另外,你还可以通过查看JVM的内存快照(比如使用jstat工具)来分析内存占用过多的原因。这可以帮助你更好地了解内存占用情况并采取相应的措施。

四、CopyOnWriteArrayList.add()源码分析

public boolean add(E e) {
	// 获取独占锁
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
    	// 获取array
        Object[] elements = getArray();
        int len = elements.length;
        // 复制array到新数组,添加元素到新数组
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        // 替换数组
        setArray(newElements);
        return true;
    } finally {
	    // 释放锁
        lock.unlock();
    }
}

CopyOnWriteArrayList内部定义了一个内部array数组,然后复制array到新数组,添加元素到新数组。所有的读操作都是基于新的array对象进行的。

private transient volatile Object[] array;

final Object[] getArray() {
    return array;
}

因为上了独占锁ReentrantLock,如果多个线程调用add()方法,只会有一个线程会获得到该锁,其他线程被阻塞,直至锁被释放, 由于加了锁,所以整个操作的过程是原子性操作。

由于每次写入的时候都会对数组对象进行复制,复制过程不仅会占用双倍内存,还需要消耗 CPU 等资源,如果要保存大量元素,并放任其成长,内存和CPU将面临重大考验,场面堪比金角巨兽,后果不堪设想。

对 CopyOnWriteArrayList 每一次修改,都会重新创建一个大对象,并且原来的大对象也需要回收,这都可能会触发 GC,如果超过老年代的大小则容易触发Full GC,引起应用程序长时间停顿。

在这里插入图片描述

🏆哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师。

基于CopyOnWriteArrayList并发容器(实例讲解) 下面小编就为大家带来一篇基于CopyOnWriteArrayList并发容器(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 立即下载

相关推荐

java并发容器CopyOnWriteArrayList实现原理及源码分析

主要为大家详细介绍了java并发容器CopyOnWriteArrayList实现原理及源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

【基础】Java 并发编程(下)

Java 并发编程基础整理(下)

情绪瓜皮皮丶的学习之路 724

主流 AI 插件 之一的 Copilot 介绍

Copilot 是微软推出的一款人工智能助手,旨在通过自然语言交互帮助您提升工作效率和创造力,覆盖多平台,提供智能问答、内容生成、代码辅助等功能。其核心定位为“日常 AI 伴侣”,旨在通过自然语言交互提升工作与生活效率。

u014695938的博客 6895

【并发编程笔记】 ---- 分析CopyOnWriteArrayList及BlockingQueue(最后并发容器总结)

重点分析CopyOnWriteArrayList和ArrayBlockingQueue 最后附脑图对并发容器进行总结归纳

TheWhc 540

adb详细教程(四)-使用adb启动应用、关闭应用、清空应用数据、获取设备已安装应用列表

adb对于安卓移动端来说,是个非常重要的调试工具。通过ADB可以操作、管理设备上的应用。

公众号|软件测试老吴 3万+

GPU硬件架构与微架构深度解析34-GPU安全架构深度解析

现代GPU不仅是图形处理器,更是高性能计算平台,安全架构设计至关重要。内存加密- 保护数据在传输和存储时的安全安全启动- 确保固件和软件的完整性隔离机制- 防止不同应用间的数据泄露密钥管理- 安全存储和处理加密密钥。

2301_79143213的博客 99

CopyOnWriteArrayList 的优缺点

是 Java 并发包中一个重要的线程安全集合类,通过写时复制机制实现了高效的读操作和安全的迭代操作。它非常适合读多写少的场景,如配置管理、事件监听器列表等。然而,的写操作性能较低,内存开销较大,因此在写操作频繁或内存敏感的应用中并不适用。在实际开发中,选择使用还是其他并发集合,取决于具体的应用场景和性能需求。

Flying_Fish_roe的博客 634

Python爬虫 汽车之家 车型销量--参数分析与实现

【代码】Python爬虫 汽车之家 车型销量--参数分析与实现。

2201_76125393的博客 850

CopyOnWriteArrayList 源码剖析

CopyOnWriteArrayList&CopyOnWriteArraySet 由于ArrayList操作并发下非线程安全,因为当一个线程在读,另外一个线程在写这样会造成线程不安全,因此引出了CopyOnWriteArrayList 也叫写时复制集合,而为什么要把CopyOnWriteArraySet也在这里说的主要是这个Set内部大部分是基于CopyOnWriteArrayList实现...

qq_43731074的博客 605

PSO-BP和BP多输入多输出回归预测模型 matlab (多输入多输出)

PSO-BP和BP多输入多输出回归预测模型 matlab (多输入多输出)

算法如诗的博客 258

PX4从放弃到精通(二十二):日志

文章目录前言一、下载日志二、ulog转CSV三、利用flightplot软件分析PX4的ulog日志1 windos安装2 ubuntu18.04安装四、使用PlotJuggler分析PX4日志五、设置日志记录条件六、添加自定义日志消息 前言 PX4 1.10以上固件 QGC 一、下载日志 将飞控链接地面站,在下图页面点击“刷新”,即可看到保存的日志(前提是要有TF卡) 选择需要下载的日志,点击右侧的“下载”,然后选择目录即可进行下载,如果想擦除所有的日志,可以点击右侧的“擦除全部” 二、ulog转CS

超维空间科技的博客 6796

细数 List 的10个坑,保证你一定遇到过

今天我们主要来说一说List操作在实际使用中有哪些坑,以及面对这些坑的时候我们要怎么解决。由于篇幅的限制,我们只对一些在业务开发中常见的关键点进行梳理和介绍在实际的工作中,我们不单单是要清除不同类型容器的特性,还要选择适合的容器才能做到事半功倍。我们主要介绍了转换过程中的一些坑,以及因为操作不当造成的OOM和异常,到最后介绍了线程安全类的一些坑,让我们认识到在丰富的API下藏着许多的陷阱。在使用的过程中,需要更加充分的考虑避免这些隐患的发生。最后一张思维导图来回顾一下~

xhbzl的博客 171

DDS协议--[第一章][概述]

Data Distribute Service,数据分发服务:数据分发服务(DDS™)是一个由对象管理组(OMG)发布的以数据为中心的中间件协议和API标准。DDS集成系统中的各个组件,提供低延迟数据连接、高可靠性以及高可扩展体系结构,以适应商业级物联网(IoT)应用程序的需求。

qq_41816308的博客 1152

细数 List 的10个坑,保证你一定遇到过!

由于篇幅的限制,我们只对一些在业务开发中常见的关键点进行梳理和介绍在实际的工作中,我们不单单是要清除不同类型容器的特性,还要选择适合的容器才能做到事半功倍。我们主要介绍了转换过程中的一些坑,以及因为操作不当造成的OOM和异常,到最后介绍了线程安全类的一些坑,让我们认识到在丰富的API下藏着许多的陷阱。在使用的过程中,需要更加充分的考虑避免这些隐患的发生。最后一张思维导图来回顾一下~来源:https://juejin.cn/post/7143266514722881544。

数字世界探险者 311

LeRobot 官方论文:一个用于端到端机器人学习的开源库

本文介绍了一个名为LeRobot的开源库,旨在解决机器人学习领域的碎片化问题。该库提供了端到端的技术栈,包括统一的机器人中间件API、标准化的数据集格式(LeRobotDataset)、优化的推理栈以及多种最先进机器人学习算法的实现。LeRobot支持多种低成本开源机器人平台(如SO-10X、ALOHA-2等),通过共享中间件实现便捷的遥操作和数据收集。其数据集格式已广泛应用于社区,截至2025年9月已有16,000多个数据集公开共享。该库还支持流式处理大规模数据,降低了研究门槛。在模型方面,LeRobot

2506_90492529的博客 907

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

CopyOnWriteArrayList原理

CopyOnWriteArrayList原理 文章目录CopyOnWriteArrayList原理1、什么是CopyOnWrite容器2、CopyOnWriteArrayList的实现原理3、CopyOnWrite的缺点 1、什么是CopyOnWrite容器 CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,...

烟雨gps 4290

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

一篇了解ArrayList和CopyOnWriteArrayList

这个机制就是 fail-Fast 机制,快速失败系统,通常设计用于停止有缺陷的过程,这是一种理念,在进行系统设计时优先考虑异常情况,一旦发生异常,直接停止并上报。CopyOnWriteArrayList 是 ArrayList 的线程安全版本,读取无锁,写时有锁。可以看到get方法非常简单,直接获取内部数组第i个元素,没有其他加锁的操作。见名知意—— 写时复制, 当线程在数组上移除,添加元素时,先加锁,将原。一份,然后基于副本操作,最后将已经更改的副本覆盖原数组,释放锁。来控制锁的获取和释放。

2402_88228200的博客 1646

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

CopyOnWriteArrayList

CopyOnWriteArrayList

我从不打没有准备的仗! 9404

ArrayList和CopyOnWriteArrayList

1.ArrayList查询快而增删慢 1、底层是数组,初始化大小为10 2、插入时会判断数组容量是否足够,不够的化会进行扩容 3、所谓扩容就是新建一个数组,然后将老的数据里面的元素复制到新的数组里面 4、移除元素的时候也涉及到数组中元素的移动,删除指定index位置的元素,然后将index+1至数组最后一个元素往前移动一格 结论: ArrayList底层是数组,所以查询的时候直接根据索引可以很快地找到对应地元素,改也是如此,找到index对应元素进行替换。而增加和删除就涉及到数组元素地移动,所以会比较

mhbsoft的博客 977

CopyOnWriteArrayList深度分析

CopyOnWriteArrayList是一种适用于读多写少并发场景的线程安全数据结构。它通过写时复制的策略实现了高效的读操作和线程安全。然而,由于每次写操作都需要复制整个数组,导致写性能和内存占用都有较大的开销。在使用CopyOnWriteArrayList时,需要根据实际需求进行权衡和选择。

小阳同学的博客 1525

CopyOnWriteArrayList 实现原理

CopyOnWriteArrayList是Java并发包中提供的一个并发容器,它是个线程安全的ArrayList,写操作通过创建底层数组的新副本来实现,是一种读写分离的并发策略,我们也可以称这种容器为"写时复制器",Java并发包中类似的容器还有CopyOnWriteSet,不过在CopyOnWriteSet中任然是调用的是CopyOnWriteArrayList。 实现原理 ...

吃四碗饭的嘤嘤怪的博客 4254

CopyOnWriteArrayList详解

在 JDK1.5 之前,如果想要使用并发安全的List只能选择Vector。而Vector是一种老旧的集合,已经被淘汰。Vector对于增删改查等方法基本都加了,这种方式虽然能够保证同步,但这相当于对整个Vector加上了一把大锁,使得每个方法执行的时候都要去获得锁,导致性能非常低下JDK1.5 引入了(JUC)包,其中提供了很多线程安全且并发性能良好的容器,其中唯一的线程安全List实现就是。

Mr.W的博客 1103

CopyOnWriteArrayList源码

在 JDK1.5 之前,如果想要使用并发安全的List只能选择Vector。而Vector是一种老旧的集合,已经被淘汰。Vector对于增删改查等方法基本都加了,这种方式虽然能够保证同步,但这相当于对整个Vector加上了一把大锁,使得每个方法执行的时候都要去获得锁,导致性能非常低下。JDK1.5 引入了(JUC)包,其中提供了很多线程安全且并发性能良好的容器,其中唯一的线程安全List实现就是。

埃泽漫笔 1113
上一篇: 微服务 Spring Cloud 6,用了这么多年Docker容器,殊不知你还有这么多弯弯绕
下一篇: 微服务 Spring Cloud 7,Nacos配置中心的Pull原理,附源码
哪 吒
哪 吒 2022年度博客之星TOP 1 2022年度博客之星TOP 1 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 59万+粉丝 2953原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值