深入学习java并发编程:CopyOnWriteArrayList<E>实现
来源:互联网 发布:orcl 数据库未打开 编辑:程序博客网 时间:2024/05/21 17:10
1、CopyOnWriteArrayList涉及类图
Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非常多的并发场景中使用到。
CopyOnWriteArrayList是一个线程安全、并且在读操作式无锁的ArrayList容器,当我们往其中添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。2、CopyOnWriteArrayList的构造实现以及重要方法
transient final ReentrantLock lock = new ReentrantLock();
private volatile transient Object[] array;
以上两个是CopyOnWriteArrayList类中两个重要的数据成员, Object[] array是存放列表对象的数组,可以看到使用ReentrantLock来控制并发的对arrayList进行修改。
1) 构造器
CopyOnWriteArrayList提供了3个构造器
//默认的无参数构造器,可以看到这里与ArrayList不同,arrayList创建大小为10的数组,而CopyOnWriteArrayList创建一个大小为0的数组。
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
//根据提供的Collection ,来创建CopyOnWriteArrayList
public CopyOnWriteArrayList(Collection<? extends E> c) {
Object[] elements = c.toArray();
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elements.getClass() != Object[].class)
elements = Arrays.copyOf(elements, elements.length, Object[].class);
setArray(elements);
}
//根据已有的泛型数组,创建CopyOnWriteArrayList
public CopyOnWriteArrayList(E[] toCopyIn) {
setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
}
2)add(E e): boolean 添加元素的方法
//add方法并没有使用synchronized关键字,而是使用了ReentrantLock 来保证线程安全的,不同于ArrayList,这里每次都会创建一个新的Object数组(写时复制),,此数组大小为当前数组大小加1,将之前数组内容复制到新数组中,并将新元素添加到数组末尾,最后将引用赋值给全局数组对象。通过volatile语义保证可见性。
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();
}
}
3)remove(Object o): boolean 移除元素方法
//与add方法一样,此方法也是通过ReentrantLock 锁来保证线程安全,但他和ArrayList所采用的方法不同,首先创建一个比当前数组小1的Object数组,然后移除目标元素,复制其他元素,最后将引用赋值给全局数组对象。
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();
}
}
4)get(int index): E
//此方法非常简单,直接获取当前数组对应位置的元素,并没有加锁保护,读取的是当时的一个镜像,因此可能出现脏读现象,但是相对而言,读的性能会比较高。
public E get(int index) {
return get(getArray(), index);
}
5)addIfAbsent(E e): boolean 如果不存在,则添加元素方法
public boolean addIfAbsent(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
// Copy while checking if already present.
// This wins in the most common case where it is not present
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = new Object[len + 1];
for (int i = 0; i < len; ++i) {
if (eq(e, elements[i]))
return false; // exit, throwing away copy
else
newElements[i] = elements[i];
}
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
6)iterator(): Iterator<E> 获取遍历列表的迭代器方法
// 调用iterator方法后创建一个COWIterator对象实例,保存一个当前数组的快照,在调用next方法遍历时则仅对此快照数据进行遍历,因此遍历
CopyOnWriteArrayList时不会抛出ConcurrentModificationException。
public Iterator<E> iterator() {
return new COWIterator<E>(getArray(), 0);
}
0 0
- 深入学习java并发编程:CopyOnWriteArrayList<E>实现
- Java并发编程---CopyOnWriteArrayList
- Java并发编程:CopyOnWriteArrayList
- Java并发编程:CopyOnWriteArrayList
- java并发编程之 CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- 【Java并发编程】并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- Java并发编程:并发容器之CopyOnWriteArrayList
- java并发编程--并发容器CopyOnWriteArrayList
- win32贪吃蛇实现
- 一、C++ 函数指针
- Java中初始化顺序
- linux 下的软链和硬链
- Genymotion加速下载虚拟镜像速度慢失败Connection timeout
- 深入学习java并发编程:CopyOnWriteArrayList<E>实现
- Scala学习笔记
- STM32F0xx_DMA收发USART数据配置详细过程
- 6、单例模式
- Merge k Sorted Arrays
- application共享变量
- 键盘回车事件导致页面刷新
- xml解析之使用dom4j的api对xml文件进行CRUD(二)
- Java 正则表达式