CopyOnWriteArrayList解析

CopyOnWriteArrayList是ArrayList 的一个线程安全的变体,其中所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的。

其原理是: 初始化的时候只有一个容器,很长一段时间,这个容器数据、数量等没有发生变化,多个线程都是读取同一个容器中的数据,所以这样大家读到的数据都是唯一、一致、安全的,如果后来有线程往里面增加了一个数据,这个时候CopyOnWriteArrayList 底层实现添加的原理是先copy出一个容器(可以简称副本),再往副本容器里添加这个新的数据,最后把副本容器的引用地址赋值给之前旧的的容器地址,但是在添加这个数据的期间,其他线程如果要去读取数据,仍然是读取到旧的容器里的数据。

二、CopyOnWriteArrayList数据结构
  通过源码分析可知,CopyOnWriteArrayList使用的数据结构是数组。
CopyOnWriteArrayList 使用了一种叫 写时复制 的方法,当有新元素添加到 CopyOnWriteArrayList 时,先从原有的数组中拷贝一份出来,然后在新的数组做写操作,写完之后,再将原来的数组引用指向到新数组。
当有新元素加入的时候,创建新数组,并往新数组中加入一个新元素,这个时候,array这个引用仍然是指向原数组的。
当元素在新数组添加成功后,将array这个引用指向新数组。
CopyOnWriteArrayList 的整个add操作都是在 的保护下进行的。 
这样做是为了避免在多线程并发add的时候, 复制出多个副本出来 ,把数据搞乱了,导致最终的数组数据不是我们期望的。

三、CopyOnWriteArrayList源码分析
   3.1 类的继承关系  
public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
  说明:CopyOnWriteArrayList实现了List接口,List接口定义了对列表的基本操作;同时实现了RandomAccess接口,表示可以随机访问(数组具有随机访问的特性);同时实现了Cloneable接口,表示可克隆;同时也实现了Serializable接口,表示可被序列化。
   3.2 类的内部类
   1. COWIterator类   
static final class COWIterator<E> implements ListIterator<E> {
        /** Snapshot of the array */
        // 快照
        private final Object[] snapshot;
        /** Index of element to be returned by subsequent call to next.  */
        // 游标
        private int cursor;
        // 构造函数
        private COWIterator(Object[] elements, int initialCursor) {
            cursor = initialCursor;
            snapshot = elements;
        }
        // 是否还有下一项
        public boolean hasNext() {
            return cursor < snapshot.length;
        }
        // 是否有上一项
        public boolean hasPrevious() {
            return cursor > 0 ;
        }
        // next项
        @SuppressWarnings("unchecked" )
        public E next() {
            if (! hasNext()) // 不存在下一项,抛出异常
                throw new NoSuchElementException();
            // 返回下一项
            return (E) snapshot[cursor++ ];
        }

        @SuppressWarnings( "unchecked" )
        public E previous() {
            if (! hasPrevious())
                throw new NoSuchElementException();
            return (E) snapshot[-- cursor];
        }
       
        // 下一项索引
        public int nextIndex() {
            return cursor;
        }
       
        // 上一项索引
        public int previousIndex() {
            return cursor-1 ;
        }

        /**
         * Not supported. Always throws UnsupportedOperationException.
         * @throws UnsupportedOperationException always; { @code
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值