码迷,mamicode.com
首页 > 其他好文 > 详细

CopyOnWriteArrayList add get remove 源码解析

时间:2019-11-16 23:28:24      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:没有   throws   checked   unlock   swa   color   替换   源码解析   nbsp   

 

public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable

  直译过来,就是写时复制的动态数组。

 

add(E e)方法,使用可重入锁ReentrantLock,来保证线程安全。通过方法copy一份新的数组数据,新数组长度加1,在末端把新数据放入新数组里面,最后用新数组替代原有数组。使用可重入锁时,注意把解锁操作放在finally里面,保证解锁操作一定会被执行,避免执行过程产生异常导致锁无法释放。

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#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();
        }
    }

 

add(int index, E e)方法,

同理,操作数组之前,先加锁。

然后检查索引是否越界。

最后,把原数组分成两次copy到新的长度加1的数组上,以索引index为分界线,copy时在index处预留一个空位置,然后在索引位置放入新的数据,这样新数组构造完成,替换原来的数组,释放锁,结束。

/**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    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 = Arrays.copyOf(elements, len + 1);
            else {
                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();
        }
    }

 

get(int index )方法,简单的通过索引,直接定位数组元素。注意这里索引时,并没有索引是否越界的检查,跟ArrayList不太一样。

    /**
     * {@inheritDoc}
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        return get(getArray(), index);
    }

    @SuppressWarnings("unchecked")
    private E get(Object[] a, int index) {
        return (E) a[index];
    }

    /**
     * Gets the array.  Non-private so as to also be accessible
     * from CopyOnWriteArraySet class.
     */
    final Object[] getArray() {
        return array;
    }

 

remove(int index)方法,这个方法的实现跟上面提到的add(int index) 基本一样。只不过在这里,复制数组时,会把index位置的数据直接放弃。

/**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).  Returns the element that was removed from the list.
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    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();
        }
    }

 

CopyOnWriteArrayList add get remove 源码解析

标签:没有   throws   checked   unlock   swa   color   替换   源码解析   nbsp   

原文地址:https://www.cnblogs.com/zhangxuezhi/p/11872860.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!