java并发容器-CopyOnWriteArrayList

来源:互联网 发布:模块化编程思想 编辑:程序博客网 时间:2024/05/13 07:25

1.基本思路

        Copy-On-Write,是一种用于程序设计中的优化策略。基本思路是:从一开始大家都在共享同一个内容,当某个人想修改这个内容的时候,会把真正的内容Copy出去形成一个新的内容,然后再修改,这是一种延时懒惰策略。

       CopyOnWrite容器,即写时复制容器。通俗理解就是,当我们向一个容器中添加元素的时候,不直接向容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后向新的容器里添加元素,添加完元素后再将原容器的应用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。


2.实现原理

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

    transient final ReentrantLock lock = new ReentrantLock();    private volatile transient Object[] array;             //实际存储数据的数组    final Object[] getArray()     {        return array;    }    final void setArray(Object[] a)     {        array = a;    }

     由以上代码看出,添加元素实际上就是先复制一份原来的数组,然后直接添加至末尾,再将引用指向新数组。

     

     读数据可以不用加锁,直接读即可

    public E get(int index)     {        return get(getArray(), index);    }

3.CopyOnWrite应用场景

       Copy用于读多写少的并发场景。比如黑、白名单,商品类目的访问和更新场景。


4.CopyOnWrite缺点

     (1)数据一致性问题

             CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。如果希望写入的数据马上就能读到,就不要使用CopyOnWrite容器

     (2)内存占用问题

             因为CopyOnWrite的写时复制机制,所以在进行写操作的时候,内存里会同时驻扎2个对象,旧的对象和新写入的对象。如果这些对象占用的内存比较大,如果说200M左右,那么再写入100M数据进去,内存就会有300M,那么这个时候很可能会造成频繁的Full GC。

             针对内存占用问题,可以使用压缩容器中元素的方法来减少大对象的内存消耗。如元素全部都是10进制,可以考虑压缩为32或64进制。或者不使用CopyOnWrite容器,而使用其他并发容器,如ConcurrentHashMap




0 0
原创粉丝点击