网站首页 > 精选教程 正文
CopyOnWriteArrayList 是 Java 中 java.util.concurrent 包提供的一种线程安全的 List 实现。它特别适用于读多写少(Read-mostly)的并发场景,比如事件监听器列表、配置管理等。
核心思想
- 写时复制(Copy-On-Write)
每当对集合进行修改操作(如添加、删除、替换元素)时,它会创建一个新的数组副本,并在新副本上执行修改操作,最后再将引用指向新的数组。
而读取操作(如 get, iterator 等)不会加锁,直接访问当前数组。
- 线程安全实现
通过 volatile 关键字修饰底层数组,保证可见性;写操作通过锁(ReentrantLock)实现互斥。
每次写操作生成新数组,避免并发写冲突,但可能短暂存在多个数组副本。
特点
特性 | 描述 |
线程安全 | 所有操作都是线程安全的,不需要外部同步 |
写操作加锁 | 修改操作(add, set, remove)使用重入锁(ReentrantLock)保护 |
读不加锁 | 读操作无锁,性能高 |
最终一致性 | 迭代器或快照视图看到的是创建那一刻的数据状态 |
高开销写操作 | 每次写都要复制整个数组,适合写少读多的场景 |
不抛出 | 因为迭代基于快照 |
常用方法示例
import java.util.concurrent.CopyOnWriteArrayList;
public class CpListExample {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
// 添加元素
list.add("A");
list.add("B");
list.add("C");
// 读取元素
System.out.println(list.get(0)); // 输出 A
// 删除元素
list.remove("B");
// 遍历(不会抛出 ConcurrentModificationException)
for (String s : list) {
System.out.println(s);
}
}
}
内部原理简析
1. 内部维护一个 volatile transient Object[] array; 来保存数据。
2. 每次写操作都会复制原数组到新数组并修改新数组。
3. 使用 ReentrantLock 来保证写操作的原子性和可见性。
4. 读操作直接访问 array,因为 volatile 能确保可见性。
适用场景
适合场景:
- 大量读操作,少量写操作
- 对实时一致性要求不高(最终一致即可)
不适合场景:
- 写操作频繁
- 数据量大(每次写都复制数组,性能差)
注意事项
- 内存开销:频繁写操作会导致大量数组复制,可能引发内存和 GC 压力。
- 实时性不足:读操作可能获取旧数据,不适合强一致性场景。
- 迭代器限制:迭代器不支持修改操作(如 remove、set),调用会抛出 UnsupportedOperationException。
与 Vector / Collections.synchronizedList 对比
特性 | Vector | Collections.synchronizedList | CopyOnWriteArrayList |
线程安全 | 是 | 是 | 是 |
读写是否加锁 | 读写都加锁 | 读写都加锁 | 仅写加锁 |
并发性能 | 差 | 一般 | 好(读并发强) |
是否抛 CME | 否 | 是 | 否 |
是否支持快照遍历 | 否 | 否 | 是 |
猜你喜欢
- 2025-05-28 10亿数据量只需要100MB内存,redis的位存储为什么这么牛?
- 2025-05-28 Java 如何在 Array 和 List 之间进行转换
- 2025-05-28 Java 中,找出数组中重复数字的常见方法
- 2025-05-28 Java中判断数组是否包含特定值的方法
- 2025-05-28 【Java数组终极指南】从青铜到王者:一文解锁高效数据处理秘籍
- 2025-05-28 java数组的初始化及遍历
- 2025-05-28 Java集合与数组互转终极指南:从基础到高级应用
- 2025-05-28 Java数组作为方法参数:值传递的真相与最佳实践
- 2025-05-28 Java数组详解
你 发表评论:
欢迎- 08-06AIDA64发布7.70正式版:首次支持PCIe 7.0,提前支持Zen 6
- 08-06C#语言编程案例-颜色码数制转换
- 08-06渐变配色工具——webgradients
- 08-06CSS颜色值的转换
- 08-06KDE Plasma 6.4桌面环境发布:增强多桌面布局、优化界面等
- 08-06生成引人注目色彩的小型Javascript脚本——randomColor
- 08-06CSS入门指南:核心概念与实用技巧
- 08-06软网推荐:自定软件窗口背景色保护眼睛
- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)