CopyOnWriteArrayList源码

实现List、RandomAccess、Cloneable
List接口定义List集合的操作方法
RandomAccess实现此接口的类可以随机访问
Cloneable实现此接口的类可以进行拷贝操作
 
重要说明:
CopyOnWriteArrayList是线程安全的,
通过CopyOnWriteArrayList对象中修改方法进行加锁,保证集合的线程安全
同时对数组进行修改时,把当前对象的数组拷贝一份newElements,先对newElements进行操作,操作完再复制给对象的数组,减少对查询类操作的锁定
 
代码翻译:
public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    private static final long serialVersionUID = 8673264195747942595L;

    保护设置属性方法的锁
    final transient ReentrantLock lock = new ReentrantLock();

    只能通过getArray/setArray访问的数组
    private transient volatile Object[] array;


    获得数组,不是私有方法所以可以从CopyOnWriteArraySet访问
    final Object[] getArray() {
        return array;
    }

    设置数组
    final void setArray(Object[] a) {
        array = a;
    }

    创建一个空数组
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }

    
    根据指定的集合创建一个包含所有元素的数组
    主要方法是 Arrays.copyOf()
    public CopyOnWriteArrayList(Collection<? extends E> c) {
        Object[] elements;
        if (c.getClass() == CopyOnWriteArrayList.class)
            elements = ((CopyOnWriteArrayList<?>)c).getArray();
        else {
            elements = c.toArray();
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elements.getClass() != Object[].class)
                elements = Arrays.copyOf(elements, elements.length, Object[].class);
        }
        setArray(elements);
    }

    创建一个包含给定数组副本的列表。
    public CopyOnWriteArrayList(E[] toCopyIn) {
        setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
    }
    
    返回数组大小
    public int size() {
        return getArray().length;
    }

    判断数组是否为空
    public boolean isEmpty() {
        return size() == 0;
    }

    判断o1与o2是否相等
    private static boolean eq(Object o1, Object o2) {
        return (o1 == null) ? o2 == null : o1.equals(o2);
    }


    indexOf的静态版本,允许重复调用而不需要每次重新获得数组
    private static int indexOf(Object o, Object[] elements,
                               int index, int fence) {
        if (o == null) {
            for (int i = index; i < fence; i++)
                if (elements[i] == null)
                    return i;
        } else {
            for (int i = index; i < fence; i++)
                if (o.equals(elements[i]))
                    return i;
        }
        return -1;
    }

    lastIndexOf的静态版本
    private static int lastIndexOf(Object o, Object[] elements, int index) {
        if (o == null) {
            for (int i = index; i >= 0; i--)
                if (elements[i] == null)
                    return i;
        } else {
            for (int i = index; i >= 0; i--)
                if (o.equals(elements[i]))
                    return i;
        }
        return -1;
    }

  
    如果数组中包含指定元素,则返回true
    public boolean contains(Object o) {
        Object[] elements = getArray();
        return indexOf(o, elements, 0, elements.length) >= 0;
    }

    根据对象获得索引位置
    public int indexOf(Object o) {
        Object[] elements = getArray();
        return indexOf(o, elements, 0, elements.length);
    }

  
    返回从index索引开始,对象E第一次出现的索引位置,如果没有返回-1
    public int indexOf(E e, int index) {
        Object[] elements = getArray();
        return indexOf(e, elements, index, elements.length);
    }

    从后开始检索对象o第一次出现的位置
    public int lastIndexOf(Object o) {
        Object[] elements = getArray();
        return lastIndexOf(o, elements, elements.length - 1);
    }

    返回从index索引反向开始,对象E第一次出现的索引位置,如果没有返回-1
    public int lastIndexOf(E e, int index) {
        Object[] elements = getArray();
        return lastIndexOf(e, elements, index);
    }

    拷贝一个CopyOnWriteArrayList对象镜像,里面的数组不会被拷贝,原对象中数组与拷贝对象中数组存储在相同的堆
    重点说明在方法中调用了clone.resetLock()方法,对ReentrantLock锁进行了重置
    public Object clone() {
        try {
            @SuppressWarnings("unchecked")
            CopyOnWriteArrayList<E> clone =
                (CopyOnWriteArrayList<E>) super.clone();
            clone.resetLock();
            return clone;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    }

    返回数组
    public Object[] toArray() {
        Object[] elements = getArray();
        return Arrays.copyOf(elements, elements.length);
    }

    
    返回指定参数类型的数组对象,
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T a[]) {
        Object[] elements = getArray();
        int len = elements.length;
        //如果T数组长度小于调用方数组长度,则在调用方数组中截取长度为T的新数组
        if (a.length < len)
            return (T[]) Arrays.copyOf(elements, len, a.getClass());
        else {//如果T数组长度大于等于调用方数组长度,则新分配一个数组
            System.arraycopy(elements, 0, a, 0, len);
            if (a.length > len)
                a[len] = null;
            return a;
        }
    }

    返回数组中指定索引的值
    @SuppressWarnings("unchecked")
    private E get(Object[] a, int index) {
        return (E) a[index];
    }

    返回指定索引的值
    public E get(int index) {
        return get(getArray(), index);
    }

  
    把指定索引位置的元素值替换为element
    重点说明:
    public E set(int index, E element) {
        final ReentrantLock lock = this.lock;
        //第一步先获得锁
        lock.lock();
        try {
            //定义临时数组变量
            Object[] elements = getArray();
            //从elements获得index索引的值,oldValue
            E oldValue = get(elements, index);
            //判断oldValue与newValue是否相等
            //【if语句一定会执行,不会执行else】
            //如果不相等,生成新的数组
            if (oldValue != element) {
                int len = elements.length;
                /拷贝当前数组对象,重新分配内存创建新数组对象newElements
                Object[] newElements = Arrays.copyOf(elements, len);
                newElements[index] = element;
                //将newElements重新复制给当前对象的数组变量
                setArray(newElements);
            } else {
                // Not quite a no-op; ensures volatile write semantics
                setArray(elements);
            }
            return oldValue;
        } finally {
            //释放锁
            lock.unlock();
        }
    }

    //添加对象e
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        //第一步先获得锁
        lock.lock();
        try {
            //定义临时数组变量
            Object[] elements = getArray();
            int len = elements.length;
            //拷贝当前数组对象,重新分配内存创建新数组对象newElements
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            //释放锁
            lock.unlock();
        }
    }


    在数组指定索引插入Element对象,如果index位置有值,则原有值向右移动
    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
                newElements = Arrays.copyOf(elements, len + 1);
            else {
                //使用System.arraycopy()方法进行数组间的拷贝
                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();
        }
    }

    删除指定index位置的数据
    public E remove(int index) {
        final ReentrantLock lock = this.lock;
        //第一步先获得锁
        lock.lock();
        try {
            //定义临时数组变量
            Object[] elements = getArray();
            int len = elements.length;
            //获得oldValue
            E oldValue = get(elements, index);
            int numMoved = len - index - 1;
            //numMoved == 0代表index为数组最后一位
            if (numMoved == 0)
                //拷贝当前数组对象,重新分配内存创建新数组对象
                setArray(Arrays.copyOf(elements, len - 1));
            else {
                //如果index为非数组最后一位,则新建一个长度减一的数组,通过System.arraycopy()方式进行拷贝
                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();
        }
    }

    
    删除对象o第一次出现的数组
    public boolean remove(Object o) {
        Object[] snapshot = getArray();
        int index = indexOf(o, snapshot, 0, snapshot.length);
        return (index < 0) ? false : remove(o, snapshot, index);
    }

    从snapshot数组中删除指定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: {
                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();
        }
    }

    如果对象e不存在,则添加对象e
    public boolean addIfAbsent(E e) {
        Object[] snapshot = getArray();
        return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
            addIfAbsent(e, snapshot);
    }

    在snapshot数组中添加对象e
    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();
        }
    }
    
    //把空数组复制给对象
    public void clear() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            setArray(new Object[0]);
        } finally {
            lock.unlock();
        }
    }
    
    //对数组进行排序,先创建一个新的数组,对新数组排序后,新数组复制给对象
    public void sort(Comparator<? super E> c) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            Object[] newElements = Arrays.copyOf(elements, elements.length);
            @SuppressWarnings("unchecked") E[] es = (E[])newElements;
            Arrays.sort(es, c);
            setArray(newElements);
        } finally {
            lock.unlock();
        }
    }
}
收藏文章数量从多到少与“把书读薄”是一个道理
原文地址:https://www.cnblogs.com/use-D/p/9627873.html