CopyOnWriteArrayList(一)

1 CopyOnWriteArrayList介绍

CopyOnWriteArrayList是一个线程安全的ArrayList。
CopyOnWriteArrayList是基于lock锁和数组副本的形式去保证线程安全。
在写数据时,需要先获取lock锁,需要复制一个副本数组,将数据插入到副本数组中,将副本数组赋值给CopyOnWriteArrayList中的array。
因为CopyOnWriteArrayList每次写数据都要构建一个副本,如果你的业务是写多,并且数组中的数据量比较大,尽量避免去使用CopyOnWriteArrayList,因为这里会构建大量的数组副本,比较占用内存资源。
CopyOnWriteArrayList是弱一致性的,写操作先执行,但是副本还有落到CopyOnWriteArrayList的array属性中,此时读操作是无法查询到的。

2 核心属性&方法

主要查看2个核心属性,以及2个核心方法,还有无参构造

/** 写操作时,需要先获取到的锁资源,CopyOnWriteArrayList全局唯一的。 */
final transient ReentrantLock lock = new ReentrantLock();
/** CopyOnWriteArrayList真实存放数据的位置,查询也是查询当前array */
private transient volatile Object[] array;
// 获取array属性
final Object[] getArray() {
return array;
}
// 替换array属性
final void setArray(Object[] a) {
array = a;
}
/**
* 默认new的CopyOnWriteArrayList数组长度为0。
* 不像ArrayList,初始长度是10,每次扩容1/2, CopyOnWriteArrayList不存在这个概念
* 每次写的时候都会构建一个新的数组
*/
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}

3 读操作

CopyOnWriteArrayList的读操作就是get方法,基于数组索引位置获取数据。
方法之所以要差分成两个,是因为CopyOnWriteArrayList中在获取数据时,不单单只有一个array的数组需要获取值,还有副本中数据的值。

// 查询数据时,只能通过get方法查询CopyOnWriteArrayList中的数据
public E get(int index) {
// getArray拿到array数组,调用get方法的重载
return get(getArray(), index);
}
// 执行get(int)时,内部调用的方法
private E get(Object[] a, int index) {
// 直接拿到数组上指定索引位置的值
return (E) a[index];
}

4 写操作

CopyOnWriteArrayList是基于lock锁和副本数组的形式保证线程安全。

// 写入元素,不指定索引位置,直接放到最后的位置
public boolean add(E e) {
// 获取全局锁,并执行lock
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;
// 将副本数组,赋值给CopyOnWriteArrayList的原数组
setArray(newElements);
// 添加成功,返回true
return true;
} finally {
// 释放锁~
lock.unlock();
}
}
// 写入元素,指定索引位置。(不会覆盖数据)
public void add(int index, E element) {
// 拿锁,加锁~
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 获取原数组,还获取了原数组的长度
Object[] elements = getArray();
int len = elements.length;
// 如果索引位置大于原数组的长度,或者索引位置是小于0的。
if (index > len || index < 0)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+len);
// 声明了副本数组
Object[] newElements;
// 原数组长度 - 索引位置等到numMovedint numMoved = len - index;
// 如果numMoved为0,说明数据要放到最后面的位置
if (numMoved == 0)
// 直接走了原生态的方式,正常复制一份副本数组
newElements = Arrays.copyOf(elements, len + 1);
else {
// 数组要插入的位置不是最后一个位置
// 副本数组长度依然是原长度 + 1
newElements = new Object[len + 1];
// 将原数组从0索引位置开始复制,复制到副本数组中的前置位置
System.arraycopy(elements, 0, newElements, 0, index);
// 将原数组从index位置开始复制,复制到副本数组的index + 1往后放。
// 这时,index就空缺出来了。
System.arraycopy(elements, index, newElements, index + 1,
numMoved);
}
// 数据正常放到指定的索引位置
newElements[index] = element;
// 将副本数组,赋值给CopyOnWriteArrayList的原数组
setArray(newElements);
} finally {
// 释放锁
lock.unlock();
}
}

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

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

相关文章

Semaphore学习一

一、定义 是JUC包下的一个工具类&#xff0c;我们可以通过其限制执行的线程数量&#xff0c;达到限流的效果。 当一个线程执行时先通过其方法进行获取许可操作&#xff0c;获取到许可的线程继续执行业务逻辑&#xff0c;当线程执行完成后进行释放许可操作&#xff0c;未获取达到…

Python 全栈体系【四阶】(七)

第四章 机器学习 六、多项式回归 1. 什么是多项式回归 线性回归适用于数据呈线性分布的回归问题。如果数据样本呈明显非线性分布&#xff0c;线性回归模型就不再适用&#xff08;下图左&#xff09;&#xff0c;而采用多项式回归可能更好&#xff08;下图右&#xff09;。例…

数据安全传输基础设施平台(二)

5安全传输平台总体设计 5.1 方案特点 规范化&#xff1a;严格遵循各种相关规范设计。独立性&#xff1a;系统各子系统间互相独立&#xff0c;在保持系统间接口的前提下&#xff0c;各系统间的升级互不干扰。最小耦合性&#xff1a;各子系统进行严格功能分解&#xff0c;每个子…

PCL点云处理之点云置平(拟合平面绕中心旋转到绝对水平)(二百二十七)

PCL点云处理之点云置平(绕中心旋转到绝对水平)(二百二十七) 一、什么是点云置平二、算法流程三、算法实现一、什么是点云置平 有时候,我们处理的点云平面并非位于水平面,而是位于某个任一三维平面上,而大多数算法又只能在水平面处理,或者水平面的点云处理是相对更简单…

P2P应用

目录 一.P2P的简介 二.P2P的工作方式 1.具有集中目录服务器的P2P工作方式 2.具有全分布式结构的P2P文件共享程序 一.P2P的简介 P2P(对等连接)&#xff0c;是指两台主机在通信时&#xff0c;并不区分哪一个是服务请求方和哪一个是服务提供方。只要两台主机都运行了对等连接…

人工智能_机器学习069_SVM支持向量机_网格搜索_交叉验证参数优化_GridSearchCV_找到最优的参数---人工智能工作笔记0109

然后我们再来说一下SVC支持向量机的参数优化,可以看到 这次我们需要,test_data这个是测试数据,容纳后 train_data这个是训练数据 这里首先我们,导出 import numpy as np 导入数学计算包 from sklearn.svm import SVC 导入支持向量机包 分类器包 def read_data(path): wit…

ping: unknown host www.baidu.com

您遇到的问题表明系统无法解析 “www.baidu.com” 的域名。这通常与 DNS&#xff08;域名系统&#xff09;配置或网络连接问题有关。以下是一些解决步骤&#xff1a; 1. 检查网络连接 首先确保您的系统已连接到互联网。您可以尝试 ping 一些知名的网站或使用 IP 地址来测试连…

从事开发近20年,经历过各种技术的转变和进步

1、jsp、javabean、servlet、jdbc。 2、Struts1、hibernate、spring。 3、webwork、ibatis、spring 4、Struts2、mybatis、spring 5、spring mvc &#xff0c;spring全家桶 6、dubbo&#xff0c;disconf 微服务&#xff0c;soa 7、springboot 全家桶 8、docker 9、dock…

qt使用事件来进行文件操作

使用键盘进行操作 #include<QKeyEvent> 包含的头文件 在.h文件中添加此函数 void keyPressEvent(QKeyEvent*k); 在.cpp中的实现操作 void MainWindow::keyPressEvent(QKeyEvent*k) {if(k->modifiers()Qt::ControlModifier&&k->key()Qt::Key_S){saveAc…

AXure的情景交互

目录 导语&#xff1a; 1.erp多样性登录界面 2.主页跳转 3.省级联动​编辑 4. 下拉加载 导语&#xff1a; Axure是一种流行的原型设计工具&#xff0c;可以用来创建网站和应用程序的交互原型。通过Axure&#xff0c;设计师可以创建情景交互&#xff0c;以展示用户与系统的交…

力扣题目学习笔记(OC + Swift) 14. 最长公共前缀

14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 “”。 方法一 竖向扫描法 个人感觉纵向扫描方式比较直观&#xff0c;符合人类理解方式&#xff0c;从前往后遍历所有字符串的每一列&#xff0c;比较相同列上的…

出国旅游需要注意些什么

出国旅游是一种令人兴奋、令人期待的经历。然而&#xff0c;在进行这种经历之前&#xff0c;有几件事情是需要注意的。本文将为您介绍出国旅游需要注意的一些重要事项。首先&#xff0c;为了确保您的出国旅行顺利进行&#xff0c;您应该提前办理好您的签证和护照。不同国家对于…

swing快速入门(十七)

上一篇 Java Swing常见事件和事件监听器 事件 Java Swing中有各种各样的事件&#xff0c;其中一些常见的事件包括&#xff1a; 按钮事件&#xff08;Button Events&#xff09;&#xff1a;与按钮相关的事件&#xff0c;例如点击、释放、进入/离开按钮等。 鼠标事件&#x…

leetCode算法—5. 最长回文子串

给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s “babad” 输出&#xff1a;“bab” 解释&#xff1a;“aba” 同样是符合题意的答案。 示例 2&…

4-Docker命令之docker login

1.docker login介绍 docker login命令是用来登录到一个docker镜像仓库,如果没有指定镜像仓库地址,默认为docker hub官方仓库。如果使用docker login命令登录到官方仓库,首先需要在官方仓库注册一个账号 本次为大家演示使用docker login命令登录自己搭建的harbor私有仓库 …

treer:生成目录结构树

一、简介 treer 是一个命令行工具&#xff0c;用于生成目录结构树。 二、安装 注意&#xff1a;treer 的安装需要用到 node.js&#xff0c;安装nvm-window(node版本管理工具)的问题 打开终端输入如下命令&#xff1a; npm install treer -g 三、用法 1. treer -h 打印帮助…

Idea远程debugger调试

当我们服务部署在服务器上&#xff0c;我们想要像在本地一样debug,就可以使用idea自带的Remote JVM Debug 创建Remote JVM Debug服务器启动jar打断点进入断点 当我们服务部署在服务器上&#xff0c;我们想要像在本地一样debug,就可以使用idea自带的 Remote JVM Debug) 创建Rem…

flask搞个简单登录界面

登录界面 直接放上login.html模板&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Lo…

JVM-11-运行时栈帧结构

“栈帧”&#xff08;Stack Frame&#xff09;则是用于支持虚拟机进行方法调用和方法执行背后的数据结构&#xff0c;它也是虚拟机运行时数据区中的虚拟机栈&#xff08;Virtual MachineStack&#xff09;的栈元素。 栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回…

docker在线安装nginx

1、查看所有镜像 1、不带容器卷常规启动nginx&#xff0c;命令如下 docker run --name nginx-test -p 8089:80 -d a6bd71f48f68 2、在宿主机创建/usr/local/data/nginxdocker/目录&#xff0c;在此目录下创建html和logs文件夹&#xff0c;然后将容器内的 nginx.conf 和 html 下…