常用方法
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
/**
* Gets the array. Non-private so as to also be accessible
* from CopyOnWriteArraySet class.
*/
final Object[] getArray() {
return array;
}
final void setArray(Object[] a) {
array = a;
}
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();
}
}
public E remove(int index) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
E oldValue = get(elements, index);
int numMoved = len - index - 1;
if (numMoved == 0)
setArray(Arrays.copyOf(elements, len - 1));
else {
Object[] newElements = new Object[len - 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index + 1, newElements, index,
numMoved);
setArray(newElements);
}
return oldValue;
} finally {
lock.unlock();
}
}
add() 执行过程:
- 先加锁,作用是只能有一个线程能够添加
- 用Arrays.copy() 复制一份原数组
- 直接在新的数组后添加新的元素
- setArray(newElements) 将array 指向新的数组
- 释放锁
remove() 执行过程:
1. 先加锁
2. int numMoved = len - index - 1;判断numMoved 是否等于0相当于判断要删除的元素是否是最后一3,如果是则直接将原来的数组的长度减少1
4. 不是则先复制 index 前面的再复制index后面
5. 将array 指向新数组
6.释放锁
优缺点
优点:
- 解决多线程并发问题
- 适合读多写少的场景
缺点: - 复制数组需要占用大量内存
- 当有一个线程在进行添加操作时,另一个线程读取到的时旧的数据,并不是最新的数据,只是最终一致性,不是实时性数据。