Java常用并发容器总结(三)
时间:2022-07-24
本文章向大家介绍Java常用并发容器总结(三),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
CopyOnWriteArrayList
1.介绍
CopyOnWriteArrayList可以理解为一个线程安全的List,它的实现原理是:在写入操作时,进行一次自我复制。也就是说,对于CopyOnWriteArrayList的读操作,不加任何同步处理;当需要进行修改操作时,对原有的数据进行一次复制,将修改的内容写入副本中。写完之后,再用修改后的副本替换原来的数据。这样一来,写操作与读操作之间互不影响。CopyOnWriteArrayList的读-读操作和读-写操作之间都是可以并发执行的,只有在写-写操作之间才互斥。
2.代码分析
首先看 private volatile transient Object[] array;有关读取的操作,以get()方法为例:
public E get(int index) {
return get(getArray(), index);
}
final Object[] getArray() {
return array;
}
private volatile transient Object[] array;
CopyOnWriteArrayList内部使用一个Object[] array数组保存数据,get()方法直接获取array数组index下标处的元素,没有采用任何同步控制和锁操作,由于内部数组不会发生修改,只能被替换,因此可以保证线程安全。
下面再看修改操作的代码,以add()方法为例
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();
}
}
可以看出,整个修改操作都是在副本数组上进行的,对读取操作不会产生影响。而且,由于内部数组使用volatile关键字修饰,所以数组修改后可以立即被读线程察觉。
3.适用场景
对于读操作远远大于写操作的情况,使用CopyOnWriteArrayList可以很大程度地提高效率。但是如果写操作较多,CopyOnWriteArrayList会频繁地进行内部数组的复制,效率较低。
- 基础篇章:关于 React Native 之 ToolbarAndroid 组件的讲解
- Android M 权限最佳实践
- Android自定义ViewGroup神器-ViewDragHelper
- Android 中常见的内存泄漏
- Android 高级自定义Toast及源码解析
- 环境配置:React Native 开发环境配置 For Android
- 美团多渠道打包方案详解,速度快到白驹过隙
- 下一代Android渠道打包工具
- 01 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之业务分析与DAO层
- 通俗易懂的分析如何用Python实现一只小爬虫,爬取拉勾网的职位信息
- 我的第一个小程序(Discuz! + 微信小程序)
- 微信小程序 wx.request 的封装
- 如何用Python爬虫实现百度图片自动下载?
- 以太坊智能合约开发入门
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- SpringBoot使用MySQL访问数据
- MySQL数据库与JDBC编程
- 自动删除QQ空间指定好友的留言
- 在Ubuntu 18.04中安装VMware工具
- 微信小程序下拉刷新功能
- 详解Linux Screen让程序保持后台运行
- Python Des加密与解密实现软件注册码、机器码
- Excel VBA 在保留原单元格数据的情况下,将计算的百分比加在后面
- 入门级别的面试题——LeetCode题目19:删除链表的倒数第N个节点
- python做web接口测试零散笔记--1
- 要一遍做对——LeetCode题目20:有效的括号
- 双指针算法练习(一)
- 一般是面试的热身题——LeetCode题目21:合并两个有序链表
- LeetCode题目22:括号生成
- OpenGL ES 3.0 | 着色器编译器