码迷,mamicode.com
首页 > 其他好文 > 详细

关于CopyOnWriteArrayList

时间:2019-12-24 14:10:24      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:==   list接口   释放   安全   单元   存储结构   序列化   toc   写入   

概述

     看这个类名CopyOnWriteArrayList继承ArrayList,通过查看类声明CopyOnWriteArrayList和ArrayList不存在继承关系。两个类的特点:1)都继承List接口,是List接口实现类。2)底层存储数据都采用数组 3)添加元素操作且ArrayList.size>数组长度时,以数组的1.5倍进行扩容;CopyOnWriteArrayList的扩容方式与ArrayList完全不一样。加一个元素copy一个新数组,老元素迁移动新数组中。然后,新增元素赋给新数组中。 4)ArrayList是非线程安全的,CopyOnWriteArrayList是线程安全的。5)ArrayList会预占内存,CopyOnWriteArrayList使用多少申请多少内存。
 
类图
技术图片
技术图片
存储结构
     之前讲过,CopyOnWriteArrayList存储结构是数组。array变量数组元素类型使用Object类型,transient元素不能序列化,volatile修饰线程可见性
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
 
构造函数
     CopyOnWriteArrayList有三个构造函数,针对三种使用场景。
1)无参场景,直接new实例就可以
2)如果想Collection实例元素迁移到CopyOnWriteArrayList中,可以使用CopyOnWriteArrayList(Collection<? extends E> c) 
3)最后一种是[]数组元素迁移到CopyOnWriteArrayList中,可以使用CopyOnWriteArrayList(E[] toCopyIn)
 
添加??单元素
     首先调用ReentrantLock.lock函数上锁,若其他线程同时进入add函数处于阻塞状态。Arrays.copyOf复制一个Object[]类型新数组newElements。新元素变量e,赋给数组最后一个索引对应的值。最后调用setArray函数设置newElements变量为数组引用,ReentrantLock.unlock释放锁。
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();
}
}
 
指定索引位置插入元素
         首先调用ReentrantLock.lock函数上锁。检查index索引是否越界(index > len || index < 0),若越界抛出IndexOutOfBoundsException异常。计算numMoved,numMoved为0时Array.copyOf复制数组;numMoved不为0时,数组移动分出两部以0到index(不含index)和(index+1到最后)。数组移动完成,index索引位置赋element元素和释放锁。
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();
}
}
指定索引查找元素
public E get(int index) {
return get(getArray(), index);
}
指定索引??值替换
     源码挺简单直接看源码吧
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index);

if (oldValue != element) {
int len = elements.length;
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;
} finally {
lock.unlock();
}
}
writeObject函数
     将elements数组元素写入到ObjectOutputStream流中。
 
readObject函数
     从ObjectInputStream流实例对象保存到Object[]数组中,保存的过程会新建一个Object[]数组代替array变量。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

关于CopyOnWriteArrayList

标签:==   list接口   释放   安全   单元   存储结构   序列化   toc   写入   

原文地址:https://www.cnblogs.com/wspgbw/p/12090846.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!