CopyOnWriteArrayList源码简析
在开发中,往往读操作的使用频率会远高于其他操作,而CopyOnWriteArrayList就是一种读操作效率远高于写操作效率的List,一起来看看吧
CopyOnWriteArrayList类图:

CopyOnWrite思想
CopyOnWrite简称COW,从命名上能出是写入时复制。意思是大家公共访问一个资源,如果有人想要修改这个资源的时候,就需要复制一个副本,去修改这个副本,而对于其他人来说访问的资源还是原来的,不会发生变化。
初始化CopyOnWriteArrayList
CopyOnWriteArrayList底层也是数组实现,和集合一样拥有添加、删除、修改和读取操作。其中添加、删除、修改操作时都需要进行加锁,读操作不会加锁。我们这里只分析添加和读取操作区别,删除修改和添加的原理基本没什么区别。
初始化方式如下:
1 | /** |
初始化只会创建一个空的数组,并将array指向它。
添加元素
1 | public boolean add(E e) { |
添加数组的步骤如下:
- 获得独占锁,将添加功能加锁
- 获取原来的数组,并得到其长度
- 创建一个长度为原来数组长度+1的数组,并拷贝原来的元素给新数组
- 追加元素到新数组末尾
- 指向新数组
- 释放锁
添加这一过程是线程安全的,CopyOnWrite的核心思想就是每次添加修改的时候拷贝一个新的资源去修改,add方法在拷贝新资源的时候会讲数组的容量+1,这样虽然每次添加元素都会浪费一定的空间,单数素组的长度刚好和元素一样的时候,也就一定程度避免了扩容的开销。
获取元素
1 | final Object[] getArray() { |
因读操作天然就是安全的,因此获取元素的方法很简单。只需要根据索引获取相应的元素即可。
总结
CopyOnWriteArrayList都是线程安全的List,底层是数组实现的,而CopyOnWriteArrayList的读操作是不加锁的,而且不需要扩容,通过COW思想就能使数组容量满足要求。实现了RandomAccess接口,支持随机读取,因此更加推荐使用for循环进行遍历。在开发中,读操作会远远多于其他操作,因此使用CopyOnWriteArrayList集合效率更高。