CopyOnWriteArrayList是一種線程安全的ArrayList實(shí)現(xiàn)
它使用的是一種寫時(shí)復(fù)制的方法然低,當(dāng)有新元素添加到CopyOnWriteArrayList時(shí)审洞,先從原有的數(shù)組中拷貝一份出來里初,然后在新的數(shù)組做寫操作锅睛,寫完之后疚膊,再將原來的數(shù)組引用指向到新數(shù)組
它定義了一個(gè)內(nèi)部數(shù)組匆光,并且只能通過getArray()、setArray()操作酿联,保證操作的原子性
/** 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;
}
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
定義了一把鎖终息,對所有的寫操作上鎖,保證同一時(shí)刻只有一個(gè)線程進(jìn)行寫操作
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
示例-添加
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#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();
}
}
示例-移除
/**
* Removes the first occurrence of the specified element from this list,
* if it is present. If this list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* {@code i} such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (if such an element exists). Returns {@code true} if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
*
* @param o element to be removed from this list, if present
* @return {@code true} if this list contained the specified element
*/
public boolean remove(Object o) {
Object[] snapshot = getArray();
int index = indexOf(o, snapshot, 0, snapshot.length);
return (index < 0) ? false : remove(o, snapshot, index);
}
/**
* A version of remove(Object) using the strong hint that given
* recent snapshot contains o at the given index.
*/
private boolean remove(Object o, Object[] snapshot, int index) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] current = getArray();
int len = current.length;
if (snapshot != current) findIndex: { //java8,增加了復(fù)雜性贞让。
int prefix = Math.min(index, len);
for (int i = 0; i < prefix; i++) {
if (current[i] != snapshot[i] && eq(o, current[i])) {
index = i;
break findIndex;
}
}
if (index >= len)
return false;
if (current[index] == o)
break findIndex;
index = indexOf(o, current, index, len);
if (index < 0)
return false;
}
Object[] newElements = new Object[len - 1];
System.arraycopy(current, 0, newElements, 0, index);
System.arraycopy(current, index + 1,
newElements, index,
len - index - 1);
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
所有的讀操作都是不需要加鎖的
示例-獲取
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return get(getArray(), index);
}
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
優(yōu)缺點(diǎn)
高性能的讀取周崭,適合讀遠(yuǎn)大于寫的場景
寫操作需要拷貝數(shù)組,容易導(dǎo)致gc喳张、只能保證最終一致性续镇,不能夠保證實(shí)時(shí)讀取