CopyOnWriteArrayList 源码分析
2018-12-03 20:13
591 查看
CopyOnWriteArrayList
CopyOnWriteArrayList 是 ArrayList 的一个线程安全版本,其中所有可变操作(add、set等) 都是通过对底层数组进行一次新的复制来实现的。因此当可变操作的次数很大时, CopyOnWriteArrayList 的性能是很低的。 最佳实践:当读取操作远远超过可变操作时,才应该使用 CopyOnWriteArrayList。
创建实例
/** * 保护并发访问的锁,优先使用对象的内置监视器 (We have a mild preference * for builtin monitors over ReentrantLock when either will do.) */ final transient Object lock = new Object(); /** 底层存储元素的对象数组,只通过 getArray/setArray 访问. */ private transient volatile Object[] array; /** * 创建一个空的 CopyOnWriteArrayList 实例 */ public CopyOnWriteArrayList() { setArray(new Object[0]); } /** * 基于指定的对象数组创建 CopyOnWriteArrayList 实例 */ public CopyOnWriteArrayList(E[] toCopyIn) { setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class)); } /** * 基于指定的集合创建 CopyOnWriteArrayList 实例 */ public CopyOnWriteArrayList(Collection<? extends E> c) { Object[] elements; if (c.getClass() == CopyOnWriteArrayList.class) { elements = ((CopyOnWriteArrayList<?>)c).getArray(); } else { elements = c.toArray(); // defend against c.toArray (incorrectly) not returning Object[] // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652) if (elements.getClass() != Object[].class) { elements = Arrays.copyOf(elements, elements.length, Object[].class); } } setArray(elements); }
写入元素
/** * 将指定的元素添加到此列表的尾部 */ @Override public boolean add(E e) { // 基于synchronized 实现线程安全 synchronized (lock) { // 读取对象数组 final Object[] elements = getArray(); // 读取长度 final int len = elements.length; // 执行一次数组拷贝,容量增加 1 final Object[] newElements = Arrays.copyOf(elements, len + 1); // 写入尾部元素 newElements[len] = e; // 写入对象数组 setArray(newElements); return true; } }
如果不存在,则写入元素
/** * 如果目标元素没有在当前 CopyOnWriteArrayList 实例中,则将其添加到尾部 */ public boolean addIfAbsent(E e) { final Object[] snapshot = getArray(); return CopyOnWriteArrayList.indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : addIfAbsent(e, snapshot); } /** * 获取目标元素 o 在对象数组 elements 中的索引,起始查找索引为 index,结束索引为 fence-1 */ private static int indexOf(Object o, Object[] elements, int index, int fence) { if (o == null) { for (int i = index; i < fence; i++) { if (elements[i] == null) { return i; } } } else { for (int i = index; i < fence; i++) { if (o.equals(elements[i])) { return i; } } } return -1; } private boolean addIfAbsent(E e, Object[] snapshot) { synchronized (lock) { final Object[] current = getArray(); final int len = current.length; // 检查元素索引期间,其他线程并发修改此 CopyOnWriteArrayList if (snapshot != current) { // Optimize for lost race to another addXXX operation final int common = Math.min(snapshot.length, len); for (int i = 0; i < common; i++) { // 如果指定索引处的元素发生了变更,则判断其是否和目标元素一致 if (current[i] != snapshot[i] && Objects.equals(e, current[i])) { // 其他线程已经将目标元素加入到此 CopyOnWriteArrayList 实例中,则直接返回。 return false; } } // 再次检查元素是否已经存在 if (CopyOnWriteArrayList.indexOf(e, current, common, len) >= 0) { return false; } } // 写入元素到尾部 final Object[] newElements = Arrays.copyOf(current, len + 1); newElements[len] = e; setArray(newElements); return true; } }
批量将集合中的元素添加到 CopyOnWriteArrayList 的尾部
/** * 批量将集合中的元素添加到 CopyOnWriteArrayList 的尾部 */ @Override public boolean addAll(Collection<? extends E> c) { // 读取对象数组 final Object[] cs = c.getClass() == CopyOnWriteArrayList.class ? ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray(); // 目标集合为空 if (cs.length == 0) { return false; } synchronized (lock) { final Object[] elements = getArray(); final int len = elements.length; // 当前 CopyOnWriteArrayList 为空,并且集合的元素类型是 Object if (len == 0 && cs.getClass() == Object[].class) { // 直接写入对象数组 setArray(cs); } else { // 拷贝源数组 final Object[] newElements = Arrays.copyOf(elements, len + cs.length); // 拷贝新增数组 System.arraycopy(cs, 0, newElements, len, cs.length); // 写入对象数组 setArray(newElements); } return true; } }
读取元素
/** * 读取指定索引处的元素 */ @Override public E get(int index) { return CopyOnWriteArrayList.elementAt(getArray(), index); }
替换指定索引处的元素,并返回旧值
/** * 替换指定索引处的元素,并返回旧值 */ @Override public E set(int index, E element) { synchronized (lock) { final Object[] elements = getArray(); final E oldValue = CopyOnWriteArrayList.elementAt(elements, index); // 新值和旧值不一致时才需要更新 if (oldValue != element) { final int len = elements.length; final Object[] newElements = Arrays.copyOf(elements, len); newElements[index] = element; setArray(newElements); } else { // Not quite a no-op; ensures volatile write semantics setArray(elements); } // 返回旧值 return oldValue; } }
移除指定索引处的元素,并返回其值
/** * 移除指定索引处的元素,并返回其值 */ @Override public E remove(int index) { synchronized (lock) { final Object[] elements = getArray(); final int len = elements.length; final E oldValue = CopyOnWriteArrayList.elementAt(elements, index); final int numMoved = len - index - 1; // 1)目标索引在数组尾部,则优化处理 if (numMoved == 0) { setArray(Arrays.copyOf(elements, len - 1)); } else { // 通过两次数组拷贝实现元素迁移 final Object[] newElements = new Object[len - 1]; System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index + 1, newElements, index, numMoved); setArray(newElements); } // 返回旧值 return oldValue; } }
其他常用方法
/** * 读取元素总数 */ @Override public int size() { return getArray().length; } /** * 此 CopyOnWriteArrayList 实例是否为空 */ @Override public boolean isEmpty() { return size() == 0; } /** * 此 CopyOnWriteArrayList 实例是否包含指定元素 o */ @Override public boolean contains(Object o) { final Object[] elements = getArray(); return CopyOnWriteArrayList.indexOf(o, elements, 0, elements.length) >= 0; } /** * 目标元素在此 CopyOnWriteArrayList 实例中第一次出现的索引,不存在时返回 -1 */ @Override public int indexOf(Object o) { final Object[] elements = getArray(); return CopyOnWriteArrayList.indexOf(o, elements, 0, elements.length); } /** * 目标元素在此 CopyOnWriteArrayList 实例中最后一次出现的索引,不存在时返回 -1 */ @Override public int lastIndexOf(Object o) { final Object[] elements = getArray(); return CopyOnWriteArrayList.lastIndexOf(o, elements, elements.length - 1); } /** * 读取底层的对象数组 */ @Override public Object[] toArray() { final Object[] elements = getArray(); // 通过数组拷贝实现复制 return Arrays.copyOf(elements, elements.length); } /** * 清空此 CopyOnWriteArrayList 实例 */ @Override public void clear() { synchronized (lock) { setArray(new Object[0]); } } /** * 顺序消费此 CopyOnWriteArrayList 实例中的每一个元素 */ @Override public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); for (final Object x : getArray()) { @SuppressWarnings("unchecked") final E e = (E) x; action.accept(e); } } /** * 对此 CopyOnWriteArrayList 实例中的元素进行排序 * created by ZXD at 3 Dec 2018 T 20:18:28 * @param c */ @Override public void sort(Comparator<? super E> c) { synchronized (lock) { sort(c, 0, getArray().length); } } @SuppressWarnings("unchecked") void sort(Comparator<? super E> c, int i, int end) { final Object[] es = getArray().clone(); Arrays.sort(es, i, end, (Comparator<Object>)c); setArray(es); }
相关文章推荐
- CopyOnWriteArrayList 并发集合源码分析
- 源码分析-CopyOnWriteArrayList
- CopyOnWriteArrayList 并发集合源码分析
- CopyOnWriteArrayList源码分析
- CopyOnWriteArrayList 并发集合源码分析
- CopyOnWriteArrayList 源码分析
- Java 并发 --- CopyOnWriteArrayList 源码分析
- CopyOnWriteArrayList 并发集合源码分析
- CopyOnWriteArrayList源码分析
- CopyOnWriteArrayList 并发集合源码分析
- CopyOnWriteArrayList-源码分析
- java并发容器CopyOnWriteArrayList实现原理及源码分析
- CopyOnWriteArrayList实现原理及源码分析
- Java多线程 -- JUC包源码分析2 -- Copy On Write/CopyOnWriteArrayList/CopyOnWriteArraySet
- 【JUC】JDK1.8源码分析之CopyOnWriteArrayList(六)
- CopyOnWriteArrayList 源码阅读与分析
- CopyOnWriteArrayList 源码分析
- Java CopyOnWriteArrayList 源码分析
- 【Java8源码分析】并发包-CopyOnWriteArrayList
- Java多线程 -- JUC包源码分析2 -- Copy On Write/CopyOnWriteArrayList/CopyOnWriteArraySet