code is shown as following
public class TestCopyOnWriteArrayList {
public static void main(String[] args) {
CopyOnWriteArrayList<Object> list = new CopyOnWriteArrayList<Object>();
Object o = new Object();
list.add(o);
System.out.println(o);
o = new Object();
list.add(o);
System.out.println(o);
o = new Object();
list.add(o);
System.out.println(o);
print("============== use for loop to traverse and meanwhile remove=============");
Exception exception = null;
try {
for(int i = 0, len = list.size(); i < len; i++) { //这里for循环里面len首次就初始化好了,
Object o1 = list.get(i); //二这里get(i)是课变化的,随着不停的remove,list里面真实的元素个数越来越小
System.out.println(o1); // 自然而然会抛出异常
list.remove(0);
}
} catch (Exception e) {
exception = e;
}
if(exception != null) {
StackTraceElement[] stackTrace = exception.getStackTrace();
for (int len = stackTrace.length,i = len - 1; i>= 0; i--) {
System.out.println(stackTrace[i].toString());
}
}
print("============== iteratively traverse and remove=============");
for (Object o1 : list) { //使用iterator 迭代器进行遍历,遍历的一直是最初的那个数组,所以这里不受影响,不会抛出异常
System.out.println(o1);
list.remove(0);
}
print();
print("==============iteratively traverse traverse=============");
for (Object o1 : list) {
System.out.println(o1);
// list.remove(0);
}
}
}
output
java.lang.Object@61bbe9ba
java.lang.Object@610455d6
java.lang.Object@511d50c0
============== use for loop to traverse and meanwhile remove=============
java.lang.Object@61bbe9ba
java.lang.Object@511d50c0
exercise.concurrency.TestCopyOnWriteArrayList.main(TestCopyOnWriteArrayList.java:28)
java.util.concurrent.CopyOnWriteArrayList.get(CopyOnWriteArrayList.java:396)
java.util.concurrent.CopyOnWriteArrayList.get(CopyOnWriteArrayList.java:387)
============== iteratively traverse and remove=============
java.lang.Object@511d50c0
==============iteratively traverse traverse=============
下面对分析CopyOnWriteArrayList里面典型的操作进行源码简易分析
CopyOnWriteArrayList里面的数据结构
public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 8673264195747942595L;
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
static final class COWIterator<E> implements ListIterator<E> {
/** Snapshot of the array */
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++];
}
}
}
执行remove方法时,没执行一次都会生成一个新的array,里面的add系列方法也是如此
final void setArray(Object[] a) {
array = a;
}
public boolean remove(Object o) {
Object[] snapshot = getArray();
int index = indexOf(o, snapshot, 0, snapshot.length);
return (index < 0) ? false : remove(o, snapshot, index);
}
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();
}
}
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: {
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();
}
}
强for循环遍历时,其实是采用的迭代器进行遍历
final Object[] getArray() {
return array;
}
//获取最初的array作为迭代器的元素
public Iterator<E> iterator() {
return new COWIterator<E>(getArray(), 0);
}
private COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
snapshot = elements;
}
public boolean hasNext() {
return cursor < snapshot.length;
}
public E next() {
if (! hasNext())
throw new NoSuchElementException();
return (E) snapshot[cursor++];
}
for循环遍历时,其实是采用的迭代器进行遍历,size()方法直接获取array的length
//
public int size() {
return getArray().length;
}
// 直接根据索引获取数组的某个元素
public E get(int index) {
return get(getArray(), index);
}