CopyOnWriteArrayList 源码分析 基于jdk1.8
CopyOnWriteArrayList 源码分析:
1:成员属性:
final transient ReentrantLock lock = new ReentrantLock(); //内部是通过ReentrantLock来保证线程安全的,通过一个非公平锁
private transient volatile Object[] array; 维护一个Object数组
2:构造方法 初始化一个长度为0 的Object数组 new Object[0]
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
setArray方法如下:
final void setArray(Object[] a) {
array = a; //将初始化后的Object 数组赋值给array成员变量
}
到此初始化方法结束:主要做了以下两个初始化过程:
1:初始化创建一个长度为0 的Object数组,并且赋值给 array成员变量
2:初始化一个ReentrantLock 非公平可重入锁,之后用于保证线程安全
3:add 方法分析:以第一次添加元素元素额为例 e=”aa”
public boolean add(E e) { // e=aa
final ReentrantLock lock = this.lock; //使用初始化构建的ReentrantLock
lock.lock(); //加锁
try {
Object[] elements = getArray(); //获取数组成员变量array,这里为Object[0]
int len = elements.length; // len=0
Object[] newElements = Arrays.copyOf(elements, len + 1); //copy elements到新数组中 长度为len+1
newElements[len] = e; //将需要add的元素放置到newElements 的len索引位置
setArray(newElements); //将新数组赋值给成员变量array
return true;
} finally {
lock.unlock(); //释放锁
}
}
Get 方法分析:
public E get(int index) {
return get(getArray(), index); //获取成员变量array 数组的index 位置处的元素
}
总结:CopyOnWriteArrayList 每次添加一个元素的时候都会进行一下拷贝,将原始数组拷贝到长度是原始数组+1的新数组中,并且将新数组赋值给成员变量array.对性能有一定的影响;而对于读则直接读取索引的位置,效率很高。