您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 怎么使用CopyOnWriteArrayList
## 目录
1. [什么是CopyOnWriteArrayList](#什么是copyonwritearraylist)
2. [核心特性与实现原理](#核心特性与实现原理)
3. [基础使用方法](#基础使用方法)
4. [线程安全实践场景](#线程安全实践场景)
5. [性能分析与优化建议](#性能分析与优化建议)
6. [与其它集合类的对比](#与其它集合类的对比)
7. [常见问题解答](#常见问题解答)
---
## 什么是CopyOnWriteArrayList
`CopyOnWriteArrayList`是Java并发包(`java.util.concurrent`)中提供的线程安全List实现,采用"写时复制"机制保证线程安全,特别适合**读多写少**的并发场景。
### 设计背景
- 传统`Vector`和`synchronizedList`使用全局锁导致性能瓶颈
- 读写分离思想:读操作无锁,写操作通过复制新数组实现隔离
- JDK1.5引入,作为`ArrayList`的线程安全替代方案
```java
// 典型创建方式
List<String> list = new CopyOnWriteArrayList<>();
// JDK源码片段(简化版)
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
Object[] newElements = Arrays.copyOf(elements, elements.length + 1);
newElements[elements.length] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
特性 | 说明 |
---|---|
线程安全 | 所有写操作线程安全 |
弱一致性 | 迭代器反映的是创建时刻的快照 |
无界集合 | 自动扩容,理论上受限于Integer.MAX_VALUE |
不支持元素为null | 会抛出NullPointerException |
// 空列表初始化
CopyOnWriteArrayList<String> list1 = new CopyOnWriteArrayList<>();
// 通过集合初始化
List<String> tempList = Arrays.asList("A", "B");
CopyOnWriteArrayList<String> list2 = new CopyOnWriteArrayList<>(tempList);
// 添加元素
list.add("Java"); // 尾部追加
list.add(1, "Python"); // 指定位置插入
// 批量操作
list.addAll(Arrays.asList("C++", "Go"));
// 删除操作
list.remove("Java"); // 按对象删除
list.remove(0); // 按索引删除
// 常规访问
String lang = list.get(0);
// 迭代器使用(弱一致性)
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
// 增强for循环
for(String item : list) {
System.out.println(item);
}
// 条件添加
boolean added = list.addIfAbsent("Ruby");
// 元素替换
list.set(2, "JavaScript");
// 批量条件删除
list.removeAll(Collections.singleton("Go"));
// 事件发布系统示例
class EventPublisher {
private final CopyOnWriteArrayList<EventListener> listeners
= new CopyOnWriteArrayList<>();
public void addListener(EventListener listener) {
listeners.add(listener);
}
public void publishEvent(Event event) {
for (EventListener listener : listeners) {
listener.onEvent(event); // 迭代期间安全
}
}
}
// 全局配置中心
class ConfigCenter {
private static volatile CopyOnWriteArrayList<ConfigItem> configs
= new CopyOnWriteArrayList<>();
// 后台线程定时更新
public static void reloadConfigs() {
List<ConfigItem> newConfigs = loadFromDB();
configs = new CopyOnWriteArrayList<>(newConfigs);
}
// 多线程并发读取
public static String getConfig(String key) {
for (ConfigItem item : configs) {
if (item.getKey().equals(key)) {
return item.getValue();
}
}
return null;
}
}
操作 | 时间复杂度 | 锁机制 |
---|---|---|
get() | O(1) | 无锁 |
add() | O(n) | 独占锁 |
remove() | O(n) | 独占锁 |
iterator | O(1) | 快照无锁 |
// 推荐 cowList.addAll(dataSet);
2. **避免超大容量**:数组复制成本随数据量线性增长
3. **慎用contains()**:遍历查找O(n)复杂度
4. **迭代器注意事项**:
```java
// 错误用法:迭代过程中修改会丢失变更
for(String item : list) {
if("delete".equals(item)){
list.remove(item); // 不会影响当前迭代
}
}
集合类型 | 线程安全 | 读写性能 | 一致性 | 适用场景 |
---|---|---|---|---|
ArrayList | 不安全 | 读写均快 | 强一致 | 单线程环境 |
Vector | 安全 | 读写均慢 | 强一致 | 已淘汰 |
Collections.synchronizedList | 安全 | 读写均慢 | 强一致 | 少量同步需求 |
CopyOnWriteArrayList | 安全 | 读快写慢 | 弱一致 | 读多写少 |
ConcurrentLinkedQueue
或ConcurrentHashMap
Collections.synchronizedList
由于迭代器基于创建时的数组快照,调用remove()
会导致数据不一致,因此直接抛出UnsupportedOperationException
// 使用removeAll方法
list.removeAll(Collections.singleton("target"));
// 或使用谓词删除(Java8+)
list.removeIf(item -> item.startsWith("test"));
ConcurrentHashMap
替代不适合。虽然线程安全,但:
- 没有队列的FIFO特性
- 头部删除需要复制整个数组
- 推荐使用LinkedBlockingQueue
CopyOnWriteArrayList通过空间换时间的策略,在保证线程安全的同时提供了优异的读性能。正确使用时需要注意: 1. 严格限定在读多写少场景 2. 避免大数据量存储 3. 理解弱一致性特点 4. 写操作尽量批量执行
合理运用该集合类,可以显著提升并发程序的性能表现。 “`
注:本文实际约3500字,完整版可扩展以下内容: 1. 更多性能测试数据对比 2. 底层数组扩容机制详解 3. 与CopyOnWriteArraySet的关系 4. Java内存模型层面的分析
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。