CopyOnWriteArrayList 源码---JDK1.8

CopyOnWriteArrayList:通过copy一份以前元素的快照,是一种读写分离的并发策略,我们也可以称这种容器为"写时复制器"。该集合适合读多写少的场景(读没有加锁,其他更新操作均有加锁)。

    /** The lock protecting all mutators */
    final transient ReentrantLock lock = new ReentrantLock();

    /** The array, accessed only via getArray/setArray. */
    //volatile修饰,如果数组发生改变其他线程可见
    private transient volatile Object[] array;

元素添加,上锁,线程安全的,每次只允许一个线程对该集合修改。

 //添加元素到列表尾部
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        //上锁
        lock.lock();
        try {
            //获取数组的快照
            Object[] elements = getArray();
            //原数组长度
            int len = elements.length;
            //每次增加元素的时候,都会进行数组copy
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            //将新元素保存到数组中
            newElements[len] = e;
            //更新原数组
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

在指定位置上添加元素:

 //在指定位置上添加元素,支持重复元素
    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;
            //如果为0,说明要添加的位置是尾部
            if (numMoved == 0)
                //直接len+1,copy
                newElements = Arrays.copyOf(elements, len + 1);
            else {
                //创建一个新数组,长度len+1
                newElements = new Object[len + 1];
                //copy,0--->index
                System.arraycopy(elements, 0, newElements, 0, index);
                //copy,index+1--->end
                System.arraycopy(elements, index, newElements, index + 1,
                        numMoved);
            }
            newElements[index] = element;
            setArray(newElements);
        } finally {
            lock.unlock();
        }
    }

更新指定位置上的元素:

//添加元素到指定位置,如果指定位置存在相同元素,什么也不做
    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);
                //更新以前位置上的元素
                newElements[index] = element;
                setArray(newElements);
            } else {
                // Not quite a no-op; ensures volatile write semantics
                setArray(elements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }

获取指定位置上的元素:

//获取指定位置上的元素
    public E get(int index) {
        return get(getArray(), index);
    }

 //获取指定位置元素
    private E get(Object[] a, int index) {
        return (E) a[index];
    }

删除指定位置上的元素:

//删除指定位置上的元素
    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;
            //为0,说明移除的是尾部元素
            if (numMoved == 0)
                setArray(Arrays.copyOf(elements, len - 1));
            //不为0,需要将将index前后2部分数组分别copy
            else {
                Object[] newElements = new Object[len - 1];
                //copy 0--index
                System.arraycopy(elements, 0, newElements, 0, index);
                //copy index+1--->end
                System.arraycopy(elements, index + 1, newElements, index,
                        numMoved);
                //更新数组
                setArray(newElements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }
时间: 2024-11-04 21:00:10

CopyOnWriteArrayList 源码---JDK1.8的相关文章

CopyOnWriteArrayList 源码阅读与分析

CopyOnWriteArrayList 源码阅读与分析 CopyOnWriteArrayList是并发包下的一个线程安全.可以实现高并发的ArrayList 首先来看看它的构造方法: final void setArray(Object[] a) { array = a; } /** * Creates an empty list. */ public CopyOnWriteArrayList() { setArray(new Object[0]); } 可以看到,它和ArrayList有一定

jdk并发包 CopyOnWriteArrayList源码分析

CopyOnWriteArrayList是jdk1.5并法包里面用于处理高并发下,读多写少的情况下,降低锁等待的集合类.下面对该类实现做一个简要的分析 1,首先CopyOnWriteArrayList是实现了List接口,对=List接口的相关方法进行了实现. 2,下面的它的add方法,会首先加锁,然后copy原List内部的数组,然后对新数组长度加1后释放锁.由于数组copy速度很快,切在读多写少的情况下锁开销比较少 public boolean add(E e) { final Reentr

第三章 CopyOnWriteArrayList源码解析

注:在看这篇文章之前,如果对ArrayList底层不清楚的话,建议先去看看ArrayList源码解析. http://www.cnblogs.com/java-zhao/p/5102342.html 1.对于CopyOnWriteArrayList需要掌握以下几点 创建:CopyOnWriteArrayList() 添加元素:即add(E)方法 获取单个对象:即get(int)方法 删除对象:即remove(E)方法 遍历所有对象:即iterator(),在实际中更常用的是增强型的for循环去做

死磕 java集合之CopyOnWriteArrayList源码分析

欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 CopyOnWriteArrayList是ArrayList的线程安全版本,内部也是通过数组实现,每次对数组的修改都完全拷贝一份新的数组来修改,修改完了再替换掉老数组,这样保证了只阻塞写操作,不阻塞读操作,实现读写分离. 继承体系 CopyOnWriteArrayList实现了List, RandomAccess, Cloneable, java.io.Serializable等接口. Copy

CopyOnWriteArrayList源码add加锁的意义

源码 /** * 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.l

CopyOnWriteArrayList源码阅读

java.util.concurrent包中定义常见集合类对应的并发集合类,用于高效处理并发场景,其中CopyOnWriteArrayList对应就是ArrayList.顾名思义CopyOnWrite,写时拷贝,这里写包括对集合类的修改操作,都会创建一个副本. CopyOnWriteArrayList的实现 类的定义 public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, j

CopyOnWriteArrayList源码解析

CopyOnWriteArrayList是java1.5版本提供的一个线程安全的ArrayList变体. 在讲解5.1.1ArrayList的时候,有说明ArrayList的fail-fast特性,它是指在遍历过程中,如果ArrayList内容发生过修改,会抛出ConcurrentModificationException. 在多线程环境下,这种情况变得尤为突出,参见测试代码(代码基于java8): ArrayList<Integer> list = new ArrayList<>

深入集合框架之CopyOnWriteArrayList源码剖析

CopyOnWriteArrayList概述 CopyOnWriteArrayList是ArrayList的一个线程安全的变种. CopyOnWriteArrayList与ArrayList不同处就在于是否会拷贝数组和加锁. CopyOnWriteArrayList顾名思义就是写时复制的ArrayList,其意思就是在修改容器的元素时,并不是直接在原数组上修改,而是先拷贝了一份数组,然后在拷贝的数组上进行修改,修改完后将其引用赋值给原数组的引用.这样体现了读写分离,这样无论在任何时候我们都可以对

ConcurrentSkipListMap源码---JDK1.8

private V doPut(K key, V value, boolean onlyIfAbsent) { Node<K,V> z; // added node if (key == null) throw new NullPointerException(); Comparator<? super K> cmp = comparator; outer: for (;;) { //找到key对应的前继节点b for (Node<K,V> b = findPredec