CopyOnWriteArrayList内存占用过多

news2024/11/18 17:45:57

在这里插入图片描述

目录

    • 一、CopyOnWriteArrayList
    • 二、CopyOnWriteArrayList的适用场景
    • 三、CopyOnWriteArrayList内存占用过多的解决方法
    • 四、CopyOnWriteArrayList.add()源码分析

大家好,我是哪吒。

一、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架构师

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1204827.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker小技能

文章目录 I 预备知识Docker组成命名空间 (进程隔离)II 常用命令2.1 案例:流水线docker 部署2.2 删除没有使用的镜像2.3 shell 不打印错误输出2.4 阿里云流水线/jenkins忽略shell步骤中的报错https://www.runoob.com/docker/docker-architecture.html I 预备知识 Docker组成…

ElementUI表格el-table自适应高度(表头表尾固定不动)

ElementUI表格el-table自适应高度&#xff08;表头表尾固定不动&#xff09;&#xff0c;内容只在中间滚动&#xff0c;效果如图&#xff1a; 实现代码 <div class"mt-10" :style"{height:tableHeight}"><div class"operation-bar">…

15年之后再回低价的双十一,几分像从前?

文 | 螳螂观察 作者 | 易不二 今年双十一&#xff0c;全网铺天盖地的“低价”字眼&#xff0c;让人有种时空错乱的感觉。 犹记得&#xff0c;2009年双十一也是以一刀直砍到5折的低价&#xff0c;推开了一扇新世界的大门。在那个车马邮件还有网速都很慢的年月&#xff0c;人们…

深入理解强化学习——马尔可夫决策过程:随机过程和马尔可夫性质

分类目录&#xff1a;《深入理解强化学习》总目录 下图介绍了强化学习里面智能体与环境之间的交互&#xff0c;智能体得到环境的状态后&#xff0c;它会采取动作&#xff0c;并把这个采取的动作返还给环境。环境得到智能体的动作后&#xff0c;它会进入下一个状态&#xff0c;把…

【Transformer从零开始代码实现 pytoch版】(三)Decoder编码器组件:多头自注意力+多头注意力+全连接层+规范化层

解码器组件 解码器部分&#xff1a; 由N个解码器层堆叠而成每个解码器层由三个子层连接结构组成第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接第三个子层连接结构包括一个前馈全…

牛客网上收藏题目总结及重写(C语言)(3)

每日一言 如果预计中的不幸没有发生的话&#xff0c;我们就会收获意外的喜悦。 --人生的智慧 题目BC84 错因&#xff1a;忘记要使用小数除法 代码 #include <stdio.h> int main() {int i 0;int n 0;scanf("%d",&n);double sum 0;for(i1;i<n;i){su…

分享一些有趣的MATLAB提示音(代码可直接复制)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

联想笔记本Fn + A可以全选,Ctrl失效

问题&#xff1a;联想笔记本Fn A可以全选&#xff0c;ctrl失效。 原因&#xff1a;BIOS启用了Fn键和Ctrl键互换。 解决操作&#xff1a; 1.开机时一直按F2&#xff0c;进入BIOS 2.点击More Settings > 2.选取Configuration 3.将Fool Proof Fn Ctrl 设定变更为Disabled 4.按…

【算法与数据结构】491、LeetCode递增子序列

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题和【算法与数据结构】78、90、LeetCode子集I&#xff0c; II中90.子集II问题有些类似&#xff0c;…

(四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB

一、七种算法&#xff08;DBO、LO、SWO、COA、LSO、KOA、GRO&#xff09;简介 1、蜣螂优化算法DBO 蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁殖…

Outlook如何精准搜索邮件

说明&#xff1a; 使用Outlook默认的搜索时&#xff0c;会出来很多无关的信息&#xff0c;对搜索邮件带来很大的不便&#xff0c;下面介绍一个使用精准搜索的方法。 操作指引&#xff1a; 1、在outlook左上角&#xff0c;进行如下操作&#xff0c;打开“其他命令” 2、打开快…

UBoot

uboot是什么&#xff1f; 嵌入式linux系统启动过程 嵌入式系统上电后先执行uboot、然后uboot负责初始化DDR&#xff0c;初始化Flash&#xff0c;然后将OS从Flash中读取到DDR中&#xff0c;然后启动OS&#xff08;OS启动后uboot就无用了&#xff09;uboot是什么&#xff0c;ubo…

【Java】集合(二)Set

1.Set接口基本介绍 无序:存取顺序不一致不重复:可以去除重复无索引:没有带索引的方法&#xff0c;所以不能使用普通for循环遍历&#xff0c;也不能通过索引来获取元素 2.Set集合的实现类 HashSet:无序、不重复、无索引LinkedHashSet: 有序、不重复、无索引TreeSet: 可排序、不…

3、Linux库的生成和使用(核心代码是程序员不可公开的小秘密)

目录 Linux库的概念 Linux 静态库 Linux 静态库作用 Linux 静态库的创建 1. 将.c文件生成.o文件 ​编辑 2. 将所有的.o文件归档为一个静态库.a文件 Linux 静态库的使用 Linux 动态库&#xff1a; Linux 动态库作用 Linux 动态库的创建 生成.so动态库文件 ​编辑 …

推荐一份适合所有人做的副业,尤其是程序员。

我建议每个人都去尝试一下网上接单&#xff0c;这是一个门槛低、类型多样的方式&#xff0c;尤其适合程序员&#xff01; 在接单平台上&#xff0c;你可以看到各种类型的兼职。以freelancer为例&#xff0c;你可以在这里找到技术、设计、写作等类型的兼职&#xff0c;只要发挥…

广告算法资料汇总【建设中】

业内大佬 阿里妈妈技术 张俊林 王喆 萧瑟 朱小强 综合 付海军&#xff1a;基于互联网广告发展演变和思考&#xff08;附视频讲解PPT&#xff09; 广告算法工程师入门_广告与算法的博客-CSDN博客 广告算法学习笔记 20万、50万、100万的算法工程师&#xff0c;到底有什么区别…

EtherCAT转Modbus网关的 EtherCAT从站配置案例

兴达易控EtherCAT转Modbus网关&#xff08;XD-MDEC20 &#xff09;是一款具备ETHERCAT从站功能的通讯网关&#xff0c;其主要作用是将ETHERCAT网络和MODBUS-RTU网络连接起来。该网关可作为ETHERCAT总线中的从站使用&#xff0c;同时也能够连接到MODBUS-RTU总线中&#xff0c;作…

upload-labs关卡4(黑名单点空格绕过或htaccess绕过)通关思路

文章目录 前言一、回顾上一关知识点二、靶场第四关方法一通关思路1.看源码2、点空格绕过 三、靶场第四关方法二通关思路1、htaccess文件是什么2、通过上传htaccess文件进行绕过1、使用前提2、上传htaccess文件&#xff0c;然后再上传phpinfo的jpg文件 总结 前言 此文章只用于学…

轻量封装WebGPU渲染系统示例<29>- 深度模糊DepthBlur(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/DepthBlur.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: const blurRTTTex0 { diffuse: { uuid: "rtt0", …

数据结构-堆排序及其复杂度计算

目录 1.堆排序 1.1 向上调整建堆 1.2 向下调整建堆 2. 两种建堆方式的时间复杂度比较 2.1 向下调整建堆的时间复杂度 2.2 向上调整建堆的时间复杂度 Topk问题 上节内容&#xff0c;我们讲了堆的实现&#xff0c;同时还包含了向上调整法和向下调整法&#xff0c;最后我们…