java.util.concurrent.CopyOnWriteArrayList
CopyOnWriteArrayList是线程安全的ArrayList, 使用ReentrantLock来保证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();
}
}
add()方法是CopyOnWriteArrayList作为ArrayList线程安全版本最重要的方法,代码本身很简单
1. 内部用Object数组存储对象
private transient volatile Object[] array;
2. get(), index()等获取元素时的方法都是不加锁的
3. 所有add(), addAll(), addIfAbsent(), set() 等添加元素的过程
- 使用ReentrantLock加锁,实现线程安全
final ReentrantLock lock = this.lock;
lock.lock();
- 产生一个指向内部Object[]数组容器的【引用】,不是【直接】使用内部对象,因为如果直接使用,当add()修改了数组,而get()去获取原来数组,会报错
Object[] elements = getArray();
- Arrays.copyOf()生成新的,长度+1的数组,然后存放要放入的对象,并替换内部数组容器的引用
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1); //生成新数组,长度+1
newElements[len] = e; //放入要存入的对象
setArray(newElements); //替换引用
而且每次调用使用Arrays.copyOf()生成新Object[]来存储对象
- 注意内存占用,add()时会产生当前容器Object[] 数组的副本,不适合使用CopyOnWriteArrayList处理超大数组
- 每次调用会使用Arrays.copyOf(),效率不高