几句话证明你看过CopyOnWriteArrayList的源码
1.特性
CopyOnWriteArrayList 是一个并发安全的 ArrayList
(1)同ArrayList所有元素都存储在动态数组中
(2)读取元素直接获取数组对应角标上的元素(不加锁)
(3)增删改时使用ReentrantLock锁 , 拷贝一份数组快照, 只改变“拷贝数组”中的元素, 最后再赋值到 CopyOnWriteArrayList 中
(4)由于写时更改的是数组快照,所以可能读到的并不是最新的数据
2.成员修饰符
//重入锁保写操作互斥
final transient ReentrantLock lock = new ReentrantLock();
//volatile保证读可见性
private transient volatile Object[] array;
3.add方法
/**
* 添加元素到数组尾部
*/
public boolean add(E e) {
//1.获取全局ReentrantLock
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
//2.动态数组拷贝
Object[] newElements = Arrays.copyOf(elements, len + 1);
//3.将元素e添加到“拷贝数组”
newElements[len] = e;
//4.拷贝数组赋值给动态数组
setArray(newElements);
return true;
} finally {
//释放锁防异常
lock.unlock();
}
}
public void add(int index, E element) {
//1.获取全局ReentrantLock
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
//2.角标校验
int len = elements.length;
if (index > len || index < 0)
throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
Object[] newElements;
int numMoved = len - index;
//3.动态数组拷贝
if (numMoved == 0)
newElements = Arrays.copyOf(elements, len + 1);
else {
newElements = new Object[len + 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index, newElements, index + 1,
numMoved);
}
//4.将元素e添加到“拷贝数组”
newElements[index] = element;
//5.拷贝数组赋值给动态数组
setArray(newElements);
} finally {
lock.unlock();
}
}
4.remove方法
/**
* 删除指定角标元素
*/
public E remove(int index) {
//1.获取全局ReentrantLock
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;
//2.动态数组拷贝+赋值给动态数组
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();
}
}
5.fail-safe机制
(1)需要复制集合,产生大量的无效对象,开销大
(2)无法保证读取的数据是目前原始数据结构中的数据。
public ListIterator<E> listIterator(int index) {
Object[] elements = getArray();
int len = elements.length;
if (index < 0 || index > len)
throw new IndexOutOfBoundsException("Index: "+index);
//迭代器 每次创建会将动态数组 传入到数组快照中
return new COWIterator<E>(elements, index);
}
static final class COWIterator<E> implements ListIterator<E> {
/** 动态数组快照,迭代器操作基于该快照 */
private final Object[] snapshot;
/** Index of element to be returned by subsequent call to next. */
private int cursor;
private COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
//当原始集合的数据改变,拷贝数据中的值也不会变化。
snapshot = elements;
}
public boolean hasNext() {
return cursor < snapshot.length;
}
public boolean hasPrevious() {
return cursor > 0;
}
@SuppressWarnings("unchecked")
public E next() {
if (! hasNext())
throw new NoSuchElementException();
//通过快照数据获取数据,无法保证读取的数据是最新的数据
return (E) snapshot[cursor++];
}
@SuppressWarnings("unchecked")
public E previous() {
if (! hasPrevious())
throw new NoSuchElementException();
return (E) snapshot[--cursor];
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
public void remove() {
throw new UnsupportedOperationException();
}
public void set(E e) {
throw new UnsupportedOperationException();
}
public void add(E e) {
throw new UnsupportedOperationException();
}
}
网友评论