CopyOnWriteArrayList vs ArrayList_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > CopyOnWriteArrayList vs ArrayList

CopyOnWriteArrayList vs ArrayList

 2013/11/18 21:19:43  bylijinnan  程序员俱乐部  我要评论(0)
  • 摘要:packagecom.ljn.base;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;importjava.util.concurrent.CopyOnWriteArrayList;/***总述:*1.ArrayListi不是线程安全的,CopyOnWriteArrayList是线程安全的。*2.ArrayListi读的时候不能写:在遍历时不能执行list.remove,list.add
  • 标签:list
class="java">package com.ljn.base;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 总述:
 * 1.ArrayListi不是线程安全的,CopyOnWriteArrayList是线程安全的。
 * 2.ArrayListi读的时候不能写:在遍历时不能执行list.remove,list.add;但可以执行iterator.remove。
 * CopyOnWriteArrayList则相反:可执行list.remove,list.add,但不能执行iterator.remove。
 * 3.CopyOnWriteArrayList用在“读比写频繁得多”的情形下。例如多个线程要遍历,而只有少数线程要写。
 * 这样就会有一个问题:读的时候可以写吗?可以,因为:
 * 4.CopyOnWriteArrayList在执行写操作时,会把当前数组元素复制一份,例如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();
            }
    }
       
    5.CopyOnWriteArrayList当前线程开始遍历(创建Iterator)时,只会看到当前数组的元素,在遍历过程中,
    如果原数组发生了变化(其他线程执行add或remove),当前线程是看不到的。以下是创建Iterator的源码:
    
        private final Object[] snapshot;
        private int cursor;

        private COWIterator(Object[] elements, int initialCursor) {
            cursor = initialCursor;
            snapshot = elements;
        }
        
 */
public class CopyOnWriteArrayListTest {

    public final static void main(String args[]) {
        
        testCopyOnWriteArrayList();
        
        testArrayList();
        
    }

    private static void testCopyOnWriteArrayList() {
        List<String> list = new CopyOnWriteArrayList<String>();
        list.add("a");
        list.add("b");
        Iterator<String> iterator = list.iterator();
        int j = 0;
        
        //will output current array: "a" and "b"
        while (iterator.hasNext()) {
            String item = iterator.next();
            System.out.println(item);
            list.add("c" + (j++));  //操作成功。但不会马上反映在本次while循环中,因为:
            /*
            An array you are looking at currently (lets say your iterator) will never change. 
            When you read from an array you are reading it as it was when you started reading. 
            If the CopyOnWriteArrayList changes by another thread, the array you're currently observing will not be affected
            */
            
            if (item.equals("b")) {
                list.remove(item);  //ok
            }
            //iterator.remove(); //UnsupportedOperationException
        }
        System.out.println(list);   //[a, c0, c1]
    }

    private static void testArrayList() {
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("z");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String item = iterator.next();
            System.out.println(item);
            iterator.remove(); //ok
            
            //list.remove(item);  //ConcurrentModificationException
            //list.add("c");  //ConcurrentModificationException
            //iterator.add();    //does not have this method on Iterator
        }
        System.out.println(list);   //empty list: []
    }
}
发表评论
用户名: 匿名