简介
CopyOnWriteArrayList
是Java中的一个线程安全的集合类,是ArrayList线程安全版本
,主要通过Copy-On-Write
(写时复制,简称COW)机制来保证线程安全。
Copy-On-Write机制核心思想:向一个数组中添加数据时,不直接操作原始数组,而是拷贝原始数组生成一份原始数组副本,将需要添加的数据添加到原始数组副本中,操作完成后再用原始数组副本直接替换原始数组,从而保证多个线程同时操作原始数组时的线程安全。
应用场景
CopyOnWriteArrayList
的主要应用场景:
- 读多写少的场景,
CopyOnWriteArrayList
允许多个线程同时对数据进行读操作,但同一时刻只允许一个线程对数据进行写操作,并且进行写操作时需要复制原始数据的副本,造成空间和时间的浪费。 - 允许读写数据时出现短暂不一致的场景,
CopyOnWriteArrayList
写操作完成后,需要使用更新后的数据副本替换原始数据,有可能使CopyOnWriteArrayList
中的数据出现短暂不一致。
实现原理
CopyOnWriteArrayList
类的继承关系:
-
Iterable接口:
CopyOnWriteArrayList
类实现了Iterable接口
,使得它可以被迭代遍历。通过实现iterator()方法,可以获取一个迭代器,用于遍历集合中的元素。 -
Collection接口:
CopyOnWriteArrayList
类继承了AbstractCollection
类,间接实现了Collection接口。通过实现Collection接口,CopyOnWriteArrayList
类获得了一些常用的集合操作方法,比如判断是否包含某个元素、计算集合的大小等。 -
List接口:
CopyOnWriteArrayList
类间接实现了List接口,通过继承AbstractList
类实现了List接口的一些方法。List接口定义了有序的集合,CopyOnWriteArrayList
类通过继承List接口,可以按照索引进行访问和操作集合中的元素。 -
Cloneable接口:
CopyOnWriteArrayList
类实现了Cloneable
接口,使得它可以进行克隆操作。通过实现clone()方法,可以创建CopyOnWriteArrayList
对象的副本。 -
Serializable接口:
CopyOnWriteArrayList
类实现了Serializable
接口,使得它可以进行序列化操作。通过实现writeObject()
和readObject()
方法,可以将CopyOnWriteArrayList
对象转换为字节流,并进行存储或传输。 -
RandomAccess接口:
CopyOnWriteArrayList
类实现了RandomAccess
接口,表示它可以高效地随机访问元素。RandomAccess
接口是一个标记接口,用于标识实现该接口的类可以通过索引进行快速随机访问,CopyOnWriteArrayList
类通过实现该接口,表明它可以高效地随机访问元素。
重要属性
CopyOnWriteArrayList
类中有两个重要的属性:
-
array:Object数组:用于存储
CopyOnWriteArrayList
中的数据。该属性使用transient和volatile关键字进行修饰:transient:表示序列化
CopyOnWriteArrayList
对象时,array属性不会被自动序列化。volatile:表示一个线程对
CopyOnWriteArrayList
数据的更新操作,对其他线程可见。 -
lock:ReentrantLock锁:用于保证多个线程同时对
CopyOnWriteArrayList
进行写操作的线程安全性。该属性也使用transient关键字进行修饰。
CopyOnWriteArrayList
类定义代码如下:
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
...
// ReentrantLock锁
final transient ReentrantLock lock = new ReentrantLock();
// Object数组
private transient volatile Object[] array;
...
}
构造函数
CopyOnWriteArrayList的构造函数:
/**
* 无参构造函数
*/
public CopyOnWriteArrayList() {
// 创建Object数组
setArray(new Object[0]);
}
/**
* 有参构造函数
* c:集合
*/
public CopyOnWriteArrayList(Collection<? extends E> c) {
Object[] elements;
// 如果参数c为CopyOnWriteArrayList对象,则将c中的数组直接赋值给elements数组
if (c.getClass() == CopyOnWriteArrayList.class)
elements = ((CopyOnWriteArrayList<?>)c).getArray();
else {
// 将参数c转换为数组并赋值给elements数组
elements = c.toArray();
// c.toArray might (incorrectly) not return Object[] (see 6260652)
// 如果数组(c)的类型不是Object[],则将数组(c)中的元素复制给Object数组,再将Object数组赋值给elements数组
if (elements.getClass() != Object[].class)
elements = Arrays.copyOf(elements, elements.length, Object[].class);
}
// 将CopyOnWriteArrayList的array属性指向elements数组
setArray(elements);
}
/**
* 有参构造函数
* toCopyIn:数组
*/
public