• 《java.util.concurrent 包源码阅读》08 CopyOnWriteArrayList和CopyOnWriteArraySet


    CopyOnWriteArrayList和CopyOnWriteArraySet从数据结构类型上来说是类似的,都是用数组实现的保存一组数据的数据结构,区别也简单就是List和set的区别。因此这里就先讨论CopyOnWriteArrayList,然后再说CopyOnWriteArraySet。

    这里重点关注的是CopyOnWrite,从字面上很容易理解,每当写操作的时候复制存储数据的数组,把拷贝上修改完再覆盖原先的数组。那么这样的数据结构适用的情况必然是读操作占绝大多数(很少进行写操作),且数据量不大的场合(例如黑名单)。

    因此再来看CopyOnWriteArrayList的实现就很好理解了,必然会有一个volatile的数组,一把锁用于写操作(读操作的时候是不要锁的)。

        /** The lock protecting all mutators */
        transient final ReentrantLock lock = new ReentrantLock();
    
        /** The array, accessed only via getArray/setArray. */
        private volatile transient Object[] array;

    复制整个数组使用Arrays.copyOf,部分复制数组使用System.arraycopy。下面以add方法为例:

        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();
            }
        }

    可以看到如果在最后添加元素,则使用Arrays.copyOf新建并复制整个数组,如果在中间插入,则使用System.arraycopy分两段复制,然后插入元素。setArray方法的作用就是覆盖原来的数组,代码如下:

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

    下面来简单谈谈CopyOnWriteArraySet,其实CopyOnWriteArraySet就是一个CopyOnWriteArrayList的包装类:

    private final CopyOnWriteArrayList<E> al;

    区别在于因为Set不允许重复元素,因此CopyOnWriteArraySet的add方法调用的是CopyOnWriteArrayList的addIfAbsent方法

        public boolean add(E e) {
            return al.addIfAbsent(e);
        }
  • 相关阅读:
    android 图表
    android assets 文件路径,与文件是否存在
    WebKit 与Chromium
    android footerView 的使用
    android gif
    webkit 介绍
    java 内存优化2
    jive论坛
    ajax josn
    jsp 数据饼图
  • 原文地址:https://www.cnblogs.com/wanly3643/p/3907246.html
Copyright © 2020-2023  润新知