hello啊,各位观众姥爷们!!!本baby今天来报道了!哈哈哈哈哈嗝
CopyOnWriteArrayList 是 Java 并发包(java.util.concurrent
)中提供的线程安全列表,基于“写时复制”(Copy-On-Write)机制实现。它适用于读多写少的高并发场景,如事件监听器列表、配置管理等。
特性 | 说明 |
---|---|
线程安全 | 读操作无锁,写操作通过锁保证线程安全。 |
数据一致性 | 读操作基于快照,迭代期间不会抛出 ConcurrentModificationException 。 |
写开销 | 每次修改操作会复制底层数组,内存占用较高。 |
适用场景 | 读操作频繁,写操作极少(如监听器管理、配置存储)。 |
数据结构
volatile Object[] array
)存储数据。写时复制(COW)
ReentrantLock
)。setArray(newArray)
)。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();
}
}
迭代器
remove
、set
),调用会抛出 UnsupportedOperationException
。public Iterator<E> iterator() {
return new COWIterator<E>(getArray(), 0);
}
优点 | 缺点 |
---|---|
读操作无锁,性能极高。 | 写操作内存开销大(复制全量数据)。 |
避免并发修改异常(ConcurrentModificationException )。 |
数据弱一致性(读操作可能不反映最新状态)。 |
实现简单,适合读多写少场景。 | 写操作频繁时性能急剧下降。 |
监听器列表:
如 GUI 事件监听器,注册后极少修改,但频繁触发事件(读)。
// 添加监听器(写操作少)
listeners.add(new Listener());
// 触发事件(读操作多)
for (Listener listener : listeners) {
listener.onEvent();
}
配置管理:
系统配置通常加载后很少修改,但频繁读取。
CopyOnWriteArrayList<Config> configs = loadConfigs();
// 读取配置(无锁)
String value = configs.get(0).getProperty("key");
缓存快照:
需要缓存某个时间点的数据快照供查询。
操作 | ArrayList | CopyOnWriteArrayList | Collections.synchronizedList |
---|---|---|---|
读(单线程) | O(1)(最快) | O(1)(无锁,快) | O(1)(同步开销,较慢) |
读(高并发) | 非线程安全,需外部同步 | O(1)(无锁,最快) | O(1)(同步开销,慢) |
写(单线程) | O(1)(快) | O(n)(复制数组,慢) | O(1)(同步开销,较慢) |
写(高并发) | 非线程安全 | O(n)(锁竞争,最慢) | O(1)(同步开销,慢) |
避免频繁写操作:
批量写入时,优先使用 addAll
代替多次 add
,减少数组复制次数。
// 不推荐
for (String item : items) {
list.add(item);
}
// 推荐
list.addAll(items);
迭代器弱一致性:
迭代器遍历的是创建时的快照,可能无法感知后续修改。
CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>(Arrays.asList(1, 2, 3));
Iterator<Integer> it = list.iterator();
list.add(4);
while (it.hasNext()) {
System.out.print(it.next()); // 输出 1,2,3(不包含4)
}
内存监控:
大对象或超大数组可能导致内存压力,需监控堆内存使用。
ConcurrentLinkedQueue
或 ConcurrentHashMap
。synchronizedList
。