自从JDK1.5引入引入concurrentHashmap,CopyOnWriteArraylist等并发集合后,java集合体系获得了很大的完善,咱们有多了很多特殊情境的选择。 java
咱们都知道,ArrayList存数数据的结构为数组,获取数据是根据数组下标,所以获取数据速度很快,而插入(中间)数据,删除数据却须要copy数组,所以速度较慢,而相比之下, CopyOnWriteArraylist底层的存储依然是数组,可是基本操做却不大同样。
数组
好处(使用场景):并发
Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始你们都在共享同一个内容,当某我的想要修改这个内容的时候,才会真正把内容Copy出去造成一个新的内容而后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器很是有用,能够在很是多的并发场景中使用到。
app
CopyOnWriteArrayList经过修改时拷贝原数组,而获取数组时返回老数组(至关于快照),使得修改和查看(遍历)的线程操做的是不一样数组,达到避免并发修改的问题 性能
缺点(不宜使用):优化
由于CopyOnWrite的写时复制机制,因此在进行写操做的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象(注意:在复制的时候只是复制容器里的引用,只是在写的时候会建立新对象添加到新容器里,而旧容器的对象还在使用,因此有两份对象内存)。若是这些对象占用的内存比较大,好比说200M左右,那么再写入100M数据进去,内存就会占用300M,那么这个时候颇有可能形成频繁的Yong GC和Full GC。以前咱们系统中使用了一个服务因为每晚使用CopyOnWrite机制更新大对象,形成了每晚15秒的Full GC,应用响应时间也随之变长。 this
针对内存占用问题,能够经过压缩容器中的元素的方法来减小大对象的内存消耗,好比,若是元素全是10进制的数字,能够考虑把它压缩成36进制或64进制。或者不使用CopyOnWrite容器,而使用其余的并发容器,如ConcurrentHashMap。spa
CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。因此若是你但愿写入的的数据,立刻能读到,请不要使用CopyOnWrite容器。线程
每次写都要复制的操做天然形成操做性能的降低。设计
代码:
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return <tt>true</tt> (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(); } }
经过Arrays的copyOf方式复制数组,同时,写的操做是须要并发控制的,采用了显示锁
写的操做直接对新的数组执行
final Object[] getArray() { return array; }