测试CopyOnWriteArrayList的特性

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);
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值