java 集合框架-CopyOnWriteArrayList
来源:互联网 发布:哈利波特知乎 编辑:程序博客网 时间:2024/04/30 06:28
CopyOnWriteArrayList是java.util.concurrent并发包下的集合类,与集合功能与ArrayList相似,主要区别为这是线程安全类
如类名一样,在对底层数组写(修改)时,会复制一份数组进行实际操作,操作完成后修改引用为新数组;而在读的时候是直接读取数组
接下来我们来看具体的源码:
/** The lock protecting all mutators */ transient final ReentrantLock lock = new ReentrantLock(); /** The array, accessed only via getArray/setArray. */ private volatile transient Object[] array;
lock 所有的读操作,都会使用这个可重入锁保证线程安全,
array 就是实例当前的底层数组,保存着list的数据
transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中
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(); } }
public E remove(int index) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; E oldValue = get(elements, index); int numMoved = len - index - 1; if (numMoved == 0) setArray(Arrays.copyOf(elements, len - 1)); else { 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; } finally { lock.unlock(); } }
基本每个写操作都类似add方法这样:先获取锁,然后复制数组,操作完成后,修改数组引用
读操作方法基本都基本与ArrayList相似,直接读取:
@SuppressWarnings("unchecked") private E get(Object[] a, int index) { return (E) a[index]; } /** * {@inheritDoc} * * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { return get(getArray(), index); }
CopyOnWriteArrayList 读操作很快,不用获取锁,但是可能获取到的数据可能就是旧的(过期的),即存在延迟,特别是使用迭代器访问
每次获取迭代器时,迭代器实例得到一份当前的复制数组,后续实际数据改变了,已经获取的迭代器不会感知
iterator 与 listIterator 都是返回一个COWIterator实例:
public Iterator<E> iterator() { return new COWIterator<E>(getArray(), 0); } public ListIterator<E> listIterator() { return new COWIterator<E>(getArray(), 0); }
private static class COWIterator<E> implements ListIterator<E> { /** Snapshot of the array */ private final Object[] snapshot; /** Index of element to be returned by subsequent call to next. */ private int cursor; private COWIterator(Object[] elements, int initialCursor) { cursor = initialCursor; snapshot = elements; //创建迭代器实例后,底层数组的修改不会感知 } public boolean hasNext() { return cursor < snapshot.length; } public boolean hasPrevious() { return cursor > 0; } @SuppressWarnings("unchecked") public E next() { if (! hasNext()) throw new NoSuchElementException(); return (E) snapshot[cursor++]; } @SuppressWarnings("unchecked") public E previous() { if (! hasPrevious()) throw new NoSuchElementException(); return (E) snapshot[--cursor]; } public int nextIndex() { return cursor; } public int previousIndex() { return cursor-1; } public void remove() { throw new UnsupportedOperationException(); } public void set(E e) { throw new UnsupportedOperationException(); } public void add(E e) { throw new UnsupportedOperationException(); } }
从CopyOnWriteArrayList 的设计来看,这个线程安全集合类通过在写时复制操作,达到了读和写的分离,
由于每次写都需要复制一份,内存使用也多,复制也会耗时;
所以CopyOnWriteArrayList适合在读操作较多的并发场景下使用,
在常用的add方法,提供了批量的addAll方法,使用批量的方法可以减少每次添加的复制;
0 0
- java 集合框架-CopyOnWriteArrayList
- Java集合-CopyOnWriteArrayList
- Java集合--CopyOnWriteArrayList
- Java常见集合框架(五):List之CopyOnWriteArrayList
- JAVA学习---集合系列---CopyOnWriteArrayList
- 深入集合框架之CopyOnWriteArrayList源码剖析
- Java线程集合类ConcurrentHashMap&CopyOnWriteArrayList 深入
- 深入Java集合学习系列:CopyOnWriteArrayList详解
- 深入Java集合学习系列:CopyOnWriteArrayList详解
- 深入Java集合系列之六:CopyOnWriteArrayList
- 深入Java集合系列之六:CopyOnWriteArrayList
- 【JAVA集合详解】并发容器之CopyOnWriteArrayList
- Java集合的读写分离术--CopyOnWriteArrayList
- Java集合系列20之CopyOnWriteArrayList
- java CopyOnWriteArrayList
- 【Java】CopyOnWriteArrayList
- Java 多线程之线程安全集合 ConcurrentHashMap、CopyOnWriteArrayList 等
- Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
- 0118
- 【狂云歌之unity_vr】unity项目持续集成dailybuild以及多平台打包管理
- AT 指令和常见错误码
- 图片上传及预览
- 水管道游戏
- java 集合框架-CopyOnWriteArrayList
- canvas 画布在主流浏览器中的尺寸限制详细介绍
- 如何制作yum本地源
- 80c51单片机通用I/O口
- React语法一
- 第11天(就业班) servlet编程、读取web应用下的资源文件、cookie、Session技术
- linux常用命令
- 透视学理论(十一)
- 一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少.