CopyOnWriteArrayList源码分析

1)读不加锁,写加锁。

2)Copy-On-Write:写时拷贝。

3)保证最终一致性,不保证实时一致性。

4)尽量批量添加(删除):减少Copy、减少GC。

5)适用场景:读多写少。

public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    final transient ReentrantLock lock = new ReentrantLock();
    private transient volatile Object[] array;
    final Object[] getArray() {
        return array;
    }

    final void setArray(Object[] a) {
        array = a;
    }

    public E set(int index, E element) {
        final ReentrantLock lock = this.lock;
        lock.lock(); // 加锁
        try {
            Object[] elements = getArray();
            E oldValue = get(elements, index); // 旧值
            if (oldValue != element) { // 新旧值不等
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len); // 拷贝array所有元素到新数组(array.length)
                newElements[index] = element; // 在新数组中设置新值
                setArray(newElements); // array指向新数组
            } else { // 新旧值相等
                setArray(elements); // array指向新数组
            }
            return oldValue;
        } finally {
            lock.unlock(); // 释放锁
        }
    }

    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); // 拷贝array所有元素到新数组(array.length + 1)
            newElements[len] = e; // 在新array末尾添加元素
            setArray(newElements); // array指向新数组
            return true;
        } finally {
            lock.unlock(); // 释放锁
        }
    }

    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; // 计算index后置位的元素个数
            if (numMoved == 0) // index后置位不存在元素
                setArray(Arrays.copyOf(elements, len - 1)); // 拷贝index前置位所有元素到新数组(array.length - 1)
            else { // index后置位不存在元素
                Object[] newElements = new Object[len - 1]; // 建立新数组(array.length - 1)
                System.arraycopy(elements, 0, newElements, 0, index); // 拷贝index前置位所有元素到新数组
                System.arraycopy(elements, index + 1, newElements, index, numMoved);// 拷贝index后置位所有元素到新数组
                setArray(newElements); // array指向新数组
            }
            return oldValue;
        } finally {
            lock.unlock(); // 释放锁
        }
    }

    public boolean addAll(Collection<? extends E> c); // 批量添加

    public boolean removeAll(Collection<?> c); // 批量删除

    void removeRange(int fromIndex, int toIndex); // 范围删除

    ... ...
}

 

posted @ 2017-12-23 23:32  Uncle_Bjorney  阅读(109)  评论(0编辑  收藏  举报