CopyOnWriteArrayList
问题:什么是 CopyOnWriteArrayList
?
解答:
CopyOnWriteArrayList
是 Java 并发包 (java.util.concurrent
) 提供的一种 线程安全 的 List
实现,它的核心特性是 写时复制(Copy-On-Write)。即,每当执行修改操作(如 add()
、set()
、remove()
)时,都会创建 一个新的数组,修改操作会在这个新数组上进行,操作完成后再将新数组赋值给 CopyOnWriteArrayList
的内部变量。
核心特性
- 线程安全:由于读操作不需要加锁,多个线程可以并发访问,而写操作是通过复制新数组实现的,因此不会影响读取操作。
- 读写分离:读操作 (
get()
、iterator()
) 直接访问旧数组,不需要加锁;写操作 (add()
、set()
、remove()
) 创建新数组,保证了读写的并发安全。 - 适用于读多写少的场景:由于写操作的成本较高(复制整个数组),
CopyOnWriteArrayList
适合 读多写少 的应用场景,例如缓存、白名单、黑名单等。
源码分析
构造方法
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
底层是一个 Object
数组,存储数据时会复制数组。
写操作
示例: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();
}
}
分析:
- 先获取当前数组
elements
。 - 复制新数组
newElements
,并将新元素放入其中。 - 用
setArray(newElements)
替换原数组,实现更新。
读操作
示例:get()
方法
public E get(int index) {
return getArray(index);
}
分析:
- 直接读取数组,无需加锁,效率高。
遍历
CopyOnWriteArrayList
通过 iterator()
进行遍历:
public