《java.util.concurrent 包源码阅读》08 CopyOnWriteArrayList和CopyOnWriteArraySet
2014-08-12 14:36
519 查看
CopyOnWriteArrayList和CopyOnWriteArraySet从数据结构类型上来说是类似的,都是用数组实现的保存一组数据的数据结构,区别也简单就是List和set的区别。因此这里就先讨论CopyOnWriteArrayList,然后再说CopyOnWriteArraySet。
这里重点关注的是CopyOnWrite,从字面上很容易理解,每当写操作的时候复制存储数据的数组,把拷贝上修改完再覆盖原先的数组。那么这样的数据结构适用的情况必然是读操作占绝大多数(很少进行写操作),且数据量不大的场合(例如黑名单)。
因此再来看CopyOnWriteArrayList的实现就很好理解了,必然会有一个volatile的数组,一把锁用于写操作(读操作的时候是不要锁的)。
复制整个数组使用Arrays.copyOf,部分复制数组使用System.arraycopy。下面以add方法为例:
可以看到如果在最后添加元素,则使用Arrays.copyOf新建并复制整个数组,如果在中间插入,则使用System.arraycopy分两段复制,然后插入元素。setArray方法的作用就是覆盖原来的数组,代码如下:
下面来简单谈谈CopyOnWriteArraySet,其实CopyOnWriteArraySet就是一个CopyOnWriteArrayList的包装类:
区别在于因为Set不允许重复元素,因此CopyOnWriteArraySet的add方法调用的是CopyOnWriteArrayList的addIfAbsent方法
这里重点关注的是CopyOnWrite,从字面上很容易理解,每当写操作的时候复制存储数据的数组,把拷贝上修改完再覆盖原先的数组。那么这样的数据结构适用的情况必然是读操作占绝大多数(很少进行写操作),且数据量不大的场合(例如黑名单)。
因此再来看CopyOnWriteArrayList的实现就很好理解了,必然会有一个volatile的数组,一把锁用于写操作(读操作的时候是不要锁的)。
/** The lock protecting all mutators */ transient final ReentrantLock lock = new ReentrantLock(); /** The array, accessed only via getArray/setArray. */ private volatile transient Object[] array;
复制整个数组使用Arrays.copyOf,部分复制数组使用System.arraycopy。下面以add方法为例:
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; if (numMoved == 0) newElements = Arrays.copyOf(elements, len + 1); else { newElements = new Object[len + 1]; System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index, newElements, index + 1, numMoved); } newElements[index] = element; setArray(newElements); } finally { lock.unlock(); } }
可以看到如果在最后添加元素,则使用Arrays.copyOf新建并复制整个数组,如果在中间插入,则使用System.arraycopy分两段复制,然后插入元素。setArray方法的作用就是覆盖原来的数组,代码如下:
final void setArray(Object[] a) { array = a; }
下面来简单谈谈CopyOnWriteArraySet,其实CopyOnWriteArraySet就是一个CopyOnWriteArrayList的包装类:
private final CopyOnWriteArrayList<E> al;
区别在于因为Set不允许重复元素,因此CopyOnWriteArraySet的add方法调用的是CopyOnWriteArrayList的addIfAbsent方法
public boolean add(E e) { return al.addIfAbsent(e); }
相关文章推荐
- java.util.concurrent.CopyOnWriteArrayList CopyOnWriteArraySet
- JAVA提高二十:CopyOnWriteArrayList&CopyOnWriteArraySet&ConcurrentHashMap介绍
- Java:concurrent包下面的Collection接口框架图( CopyOnWriteArraySet, CopyOnWriteArrayList,ConcurrentLinkedQueue,BlockingQueue)
- java.util.concurrent.CopyOnWriteArraySet
- JAVA 多线程随笔 (三) 多线程用到的并发容器 (ConcurrentHashMap,CopyOnWriteArrayList, CopyOnWriteArraySet)
- Java中的Copy-On-Write容器,CopyOnWriteArrayList和CopyOnWriteArraySet
- java.util.concurrent 之CopyOnWriteArrayList
- java.util.concurrent.CopyOnWriteArrayList
- Java多线程 -- JUC包源码分析2 -- Copy On Write/CopyOnWriteArrayList/CopyOnWriteArraySet
- java.util.concurrent.CopyOnWriteArrayList
- 【Java并发】 - CopyOnWriteArrayList,CopyOnWriteArraySet原理
- Java并发容器之CopyOnWriteArraySet与ConcurrentSkipListSet
- java数据结构:ConcurrentSkipListSet&lt;E&gt;与CopyOnWriteArraySet&lt;E&gt;
- JAVA多线程 之 CopyOnWriteArrayList和CopyOnWriteArraySet
- concurrent包下面的Collection接口框架图( CopyOnWriteArraySet, CopyOnWriteArrayList,ConcurrentLinkedQueue,Block
- Java中的Copy-On-Write容器(二) --CopyOnWriteArraySet
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- Java多线程 -- JUC包源码分析2 -- Copy On Write/CopyOnWriteArrayList/CopyOnWriteArraySet
- 学学JUC(三)-- CopyOnWriteArrayList和CopyOnWriteArraySet
- 【JDK】:CopyOnWriteArrayList、CopyOnWriteArraySet 源码解析