类简介,主要的特性为:
读方法不加锁,修改方法加锁,避免所线程场景所引起的问题,加锁使用 final transient ReentrantLock lock = new ReentrantLock(); 来实现锁的获取和释放
/**
* 该类是ArrayList的一个变体,是线程安全的,所有变更操作(add/set..)都被设计为对底层数组的全新的一个复制操作。
* 怎么理解呢:就是所每次经过add/set等改变结构的操作后,底层数组都是重新创建的,而不是和arraylist一样,在数组的基础上进行增删。
* 稍后我们可以通过add(),对这个结论进行验证
* A thread-safe variant of {@link java.util.ArrayList} in which all mutative
* operations ({@code add}, {@code set}, and so on) are implemented by
* making a fresh copy of the underlying array.
*
* 但是,当遍历操作的数量远远超过突变时,可能比替代方法更有效,并且当您不能或不想同步遍历,但又需要防止并发线程之间的干扰时,会很有用。
* 快照模式的迭代器方法使用了一个在迭代器被创建时,对数组状态的引用。数组在整个迭代器的生命周期内不能被改变。
* 因此不存在冲突,并且迭代器保证不会抛出 ConcurrentModificationException异常。当迭代器创建后,迭代器不会反映增加/删除或者list的改变。
* 迭代器本身不支持元素的add/remove/set等改变操作,这些方法会抛出 UnsupportedOperationException异常。
* <p>This is ordinarily too costly, but may be <em>more</em> efficient
* than alternatives when traversal operations vastly outnumber
* mutations, and is useful when you cannot or don't want to
* synchronize traversals, yet need to preclude interference among
* concurrent threads. The "snapshot" style iterator method uses a
* reference to the state of the array at the point that the iterator
* was created. This array never changes during the lifetime of the
* iterator, so interference is impossible and the iterator is
* guaranteed not to throw {@code ConcurrentModificationException}.
* The iterator will not reflect additions, removals, or changes to
* the list since the iterator was created. Element-changing
* operations on iterators themselves ({@code remove}, {@code set}, and
* {@code add}) are not supported. These methods throw
* {@code UnsupportedOperationException}.
*
* <p>All elements are permitted, including {@code null}.
*
* 内存一致性影响:和其他并发集合一样,一个线程先放入元素,另外一个线程删除了整个元素。造成内存的不一致。
* <p>Memory consistency effects: As with other concurrent
* collections, actions in a thread prior to placing an object into a
* {@code CopyOnWriteArrayList}
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
* actions subsequent to the access or removal of that element from
* the {@code CopyOnWriteArrayList} in another thread.
*
*/
具体方法分析:
add()方法:实现的效果和之前文章中分析的ArrayList源码分析t源码分析,LinkedList源码分析都是一样的,向当前列表中添加元素,但是实现方法不同,通过 final transient ReentrantLock lock = new ReentrantLock(); 来获取和释放锁对象。
比较核心的一行代码为:
Object[] newElements = Arrays.copyOf(elements, len + 1); // 复制了一个新的数组
复制了新的数组,并将原来数组中的元素,复制到新数组中的合适的位置,可能是末尾,可能是中间,如果是中间,会发生原有数组中元素索引位置的移动。
/**
* 向list末尾追加元素
* Appends the specified element to the end of this list.
*
*/
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();
}
}
/**
* 将元素添加到指定位置,移动其他元素到指定的位置(索引+1)
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* 超过数组边界,抛出 IndexOutOfBoundsException 异常。
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
if (index > len || index < 0)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+len);
Object[] newElements;
int numMoved = len - index;
if (numMoved == 0)
newElements = Arrays.copyOf(elements, len + 1); // 当插入到list头时,直接扩充一个数组位置
else {
newElements = new Object[len + 1];
// 否则,需要移动数组前后两部分的元素
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index, newElements, index + 1,
numMoved);
}
newElements[index] = element; // 对元素进行设置
setArray(newElements);
} finally {
lock.unlock();
}
}
添加元素时,进行判断,当前列表中不存在时,才进行添加:addIfAbsent():
/**
* 将指定list中,没包含在当前list中的元素,添加到当前list的末尾,添加元素的顺序,以指定list的iterator返回的顺序为准。
* Appends all of the elements in the specified collection that
* are not already contained in this list, to the end of
* this list, in the order that they are returned by the
* specified collection's iterator.
*
* @param c collection containing elements to be added to this list
* @return the number of elements added
* @throws NullPointerException if the specified collection is null
* @see #addIfAbsent(Object)
*/
public int addAllAbsent(Collection<? extends E> c) {
Object[] cs = c.toArray();
if (cs.length == 0)
return 0;
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
int added = 0;
// uniquify and compact elements in cs
for (int i = 0; i < cs.length; ++i) {
Object e = cs[i];
if (indexOf(e, elements, 0, len) < 0 &&
indexOf(e, cs, 0, added) < 0)
cs[added++] = e;
}
if (added > 0) {
Object[] newElements = Arrays.copyOf(elements, len + added);
System.arraycopy(cs, 0, newElements, len, added);
setArray(newElements);
}
return added;
} finally {
lock.unlock();
}
}
将指定列表中的元素,全部添加到当前列表中:
/**
* 将指定元素中所有的元素,按照指定列表的iterator返回的顺序,添加到当前list中
* Appends all of the elements in the specified collection to the end
* of this list, in the order that they are returned by the specified
* collection's iterator.
*
* @param c collection containing elements to be added to this list
* @return {@code true} if this list changed as a result of the call
* @throws NullPointerException if the specified collection is null
* @see #add(Object)
*/
public boolean addAll(Collection<? extends E> c) {
Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?
((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
if (cs.length == 0)
return false;
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
if (len == 0 && cs.getClass() == Object[].class)
setArray(cs);
else {
Object[] newElements = Arrays.copyOf(elements, len + cs.length);
System.arraycopy(cs, 0, newElements, len, cs.length);
setArray(newElements);
}
return true;
} finally {
lock.unlock();
}
}
删除元素:remove(Object o ),删除在列表中出现的元素o,如果存在多个,则删除第一个(索引数最小的元素)。
/**
* 删除list中出现的第一个指定的o。
* 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).
*/
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: { // 重新根据快照和当前数据进行比对,看过程中是否出现了对array的修改
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();
}
}
删除指定位置的元素,remove(index):
如果删除的元素,不在队尾,则需要将原有队列,以index为界,分为前后两个部分,分别插入到新的数组中。
/**
* 删除指定位置的索引,实现逻辑为:首先创建一个新的数组,长度为原来数组-1,移动原来数组中,指定元素索引的前后两部分,到新的数组中
* 如果删除的元素index ==length-1(最后一个),则直接复制1到length-1的元素到新的数组即可。
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices). Returns the element that was removed from the list.
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
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();
}
}
从队列中获取元素,get(index):
获取方法不加锁。
// Positional Access Operations
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
/**
* 获取指定索引的元素,对元素读取时,不会进行 ReentrantLock 锁操作。
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return get(getArray(), index);
}
返回列表的迭代器,其实是返回内部类COWIterator实例
/**
* 返回内部类 COWIterator 实例
* Returns an iterator over the elements in this list in proper sequence.
*
* <p>The returned iterator provides a snapshot of the state of the list
* when the iterator was constructed. No synchronization is needed while
* traversing the iterator. The iterator does <em>NOT</em> support the
* {@code remove} method.
*
* @return an iterator over the elements in this list in proper sequence
*/
public Iterator<E> iterator() {
return new COWIterator<E>(getArray(), 0);
}
/**
* 包含一个本列表的快照和初始化的游标,快照和本list相同,初始化游标为0,从头开始遍历
* Returns an iterator over the elements in this list in proper sequence.
*
* <p>The returned iterator provides a snapshot of the state of the list
* when the iterator was constructed. No synchronization is needed while
* traversing the iterator. The iterator does <em>NOT</em> support the
* {@code remove} method.
*
* @return an iterator over the elements in this list in proper sequence
*/
private COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
snapshot = elements;
}
返回list的listIterator迭代器:
/**
* {@inheritDoc}
*
* <p>The returned iterator provides a snapshot of the state of the list
* when the iterator was constructed. No synchronization is needed while
* traversing the iterator. The iterator does <em>NOT</em> support the
* {@code remove}, {@code set} or {@code add} methods.
*/
public ListIterator<E> listIterator() {
return new COWIterator<E>(getArray(), 0);
}
遍历对list中的元素进行调整:forEach():
/**
* 按照指定的action对list的元素进行处理
*/
public void forEach(Consumer<? super E> action) {
if (action == null) throw new NullPointerException();
Object[] elements = getArray();
int len = elements.length;
for (int i = 0; i < len; ++i) {
@SuppressWarnings("unchecked") E e = (E) elements[i];
action.accept(e);
}
}
保留指定list中包含的元素,对于当前list中其他的元素,则进行删除:
/**
* 删除当前列表中,元素未包含在指定列表c中的元素
* Retains only the elements in this list that are contained in the
* specified collection. In other words, removes from this list all of
* its elements that are not contained in the specified collection.
*
*/
public boolean retainAll(Collection<?> c) {
if (c == null) throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
if (len != 0) {
// temp array holds those elements we know we want to keep
int newlen = 0;
Object[] temp = new Object[len];
for (int i = 0; i < len; ++i) {
Object element = elements[i];
if (c.contains(element))
temp[newlen++] = element;
}
if (newlen != len) {
setArray(Arrays.copyOf(temp, newlen));
return true;
}
}
return false;
} finally {
lock.unlock();
}
}
添加元素时,看待添加的元素,是否已经存在于当前的列表中,如果已经存在,则不需要添加,如果不存在,才进行添加:
/**
* 如果指定的元素e在当前列表中不存在,则进行添加。否则返回false
*
* @param e element to be added to this list, if absent
* @return {@code true} if the element was added
*/
public boolean addIfAbsent(E e) {
Object[] snapshot = getArray();
return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
addIfAbsent(e, snapshot);
}
private boolean addIfAbsent(E e, Object[] snapshot) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] current = getArray();
int len = current.length;
if (snapshot != current) {
// Optimize for lost race to another addXXX operation
int common = Math.min(snapshot.length, len);
for (int i = 0; i < common; i++)
if (current[i] != snapshot[i] && eq(e, current[i]))
return false;
if (indexOf(e, current, common, len) >= 0)
return false;
}
Object[] newElements = Arrays.copyOf(current, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
根据指定的前后的索引位置,对当前列表进行截取:
针对于当前方法,需要格外注意的是,返回的列表,是建立在本列表的基础之上,任何对返回列表的修改操作,都会反映到本列表中。
/**
* 返回当前list在指定范围内的子列表,返回的列表依靠当前的列表,所以,对返回列表的修改,都会反映到当前的列表中。
* Returns a view of the portion of this list between
* {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
* The returned list is backed by this list, so changes in the
* returned list are reflected in this list.
*
* 不论当前列表经过什么方法被修改,只要不是经过返回列表进行修改,那么通过本方法返回的列表语义就会变成 undefined .
* <p>The semantics of the list returned by this method become
* undefined if the backing list (i.e., this list) is modified in
* any way other than via the returned list.
*/
public List<E> subList(int fromIndex, int toIndex) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
throw new IndexOutOfBoundsException();
return new COWSubList<E>(this, fromIndex, toIndex);
} finally {
lock.unlock();
}
}
剩余的其他方法,不再赘述:
public boolean equals(Object arg0){}
public String toString(){}
public int hashCode(){}
public Object clone(){}
public int indexOf(Object arg0,int arg1){}
public int indexOf(Object arg0){}
public void clear(){}
public boolean isEmpty(){}
public int lastIndexOf(Object arg0){}
public int lastIndexOf(Object arg0,int arg1){}
public boolean contains(Object arg0){}
public void replaceAll(UnaryOperator arg0){}
public int size(){}
public Object[] toArray(Object[] arg0){}
public Object[] toArray(){}
public boolean addAll(int arg0,Collection arg1){}
public Object set(int arg0,Object arg1){}
public boolean containsAll(Collection arg0){}
public boolean removeAll(Collection arg0){}
public ListIterator listIterator(){}
public ListIterator listIterator(int arg0){}
public boolean removeIf(Predicate arg0){}
public void sort(Comparator arg0){}
public final void wait(long arg0,int arg1) throws InterruptedException{}
public final native void wait(long arg0) throws InterruptedException{}
public final void wait() throws InterruptedException{}
public final native Class getClass(){}
public final native void notify(){}
public final native void notifyAll(){}
public Stream stream(){}
public Stream parallelStream(){}
遗留问题:
subList()方法注释中:
* 不论当前列表经过什么方法被修改,只要不是经过返回列表进行修改,那么通过本方法返回的列表语义就会变成 undefined .
* <p>The semantics of the list returned by this method become
* undefined if the backing list (i.e., this list) is modified in
* any way other than via the returned list.
具体指的是什么意思?
其他相关文章:
Java集合类框架源码分析 之 Vector源码解析 【8】
Java集合类框架源码分析 之 AttributeList源码解析 【7】
Java集合类框架源码分析 之 RoleList源码解析 【6】
Java集合类框架源码分析 之 CopyOnWriteArrayList源码解析 【5】
Java集合类框架源码分析 之 LinkedList源码解析 【4】
Java集合类框架源码分析 之 ArrayList源码解析 【3】