zoukankan      html  css  js  c++  java
  • CopyOnWriteArrayList add get remove 源码解析

    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, E e) 基本一样。只不过在这里,复制数组时,会把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();
            }
        }
  • 相关阅读:
    网页转图片,html生成图片,网页生成图片(基于linnux+phantomjs)和wkhtmltoimage
    51Nod 1031 骨牌覆盖 | Fibonacci
    51Nod 1024 矩阵中不重复的元素 | 技巧 数学
    51Nod 1014 X^2 Mod P
    51Nod 1010 只包含因子2 3 5的数 | 预处理+二分
    51Nod 1007 正整数分组 | DP (01背包)
    51Nod 1381 硬币游戏 | 概率(数学期望)
    51Nod 1347 旋转字符串 | 规律
    51Nod 1344 走格子 | 贪心
    51Nod 1305 Pairwise Sum and Divide | 思维 数学
  • 原文地址:https://www.cnblogs.com/zhangxuezhi/p/11872860.html
Copyright © 2011-2022 走看看