专业苏州房产网站建设,哪个公司做网站最好,仿制app软件多少钱,东莞人才网站1 CopyOnWriteArrayList介绍
CopyOnWriteArrayList是一个线程安全的ArrayList。 CopyOnWriteArrayList是基于lock锁和数组副本的形式去保证线程安全。 在写数据时#xff0c;需要先获取lock锁#xff0c;需要复制一个副本数组#xff0c;将数据插入到副本数组中#xff0c…1 CopyOnWriteArrayList介绍
CopyOnWriteArrayList是一个线程安全的ArrayList。 CopyOnWriteArrayList是基于lock锁和数组副本的形式去保证线程安全。 在写数据时需要先获取lock锁需要复制一个副本数组将数据插入到副本数组中将副本数组赋值给CopyOnWriteArrayList中的array。 因为CopyOnWriteArrayList每次写数据都要构建一个副本如果你的业务是写多并且数组中的数据量比较大尽量避免去使用CopyOnWriteArrayList因为这里会构建大量的数组副本比较占用内存资源。 CopyOnWriteArrayList是弱一致性的写操作先执行但是副本还有落到CopyOnWriteArrayList的array属性中此时读操作是无法查询到的。
2 核心属性方法
主要查看2个核心属性以及2个核心方法还有无参构造
/** 写操作时需要先获取到的锁资源CopyOnWriteArrayList全局唯一的。 */
final transient ReentrantLock lock new ReentrantLock();
/** CopyOnWriteArrayList真实存放数据的位置查询也是查询当前array */
private transient volatile Object[] array;
// 获取array属性
final Object[] getArray() {
return array;
}
// 替换array属性
final void setArray(Object[] a) {
array a;
}
/**
* 默认new的CopyOnWriteArrayList数组长度为0。
* 不像ArrayList初始长度是10每次扩容1/2, CopyOnWriteArrayList不存在这个概念
* 每次写的时候都会构建一个新的数组
*/
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
3 读操作
CopyOnWriteArrayList的读操作就是get方法基于数组索引位置获取数据。 方法之所以要差分成两个是因为CopyOnWriteArrayList中在获取数据时不单单只有一个array的数组需要获取值还有副本中数据的值。
// 查询数据时只能通过get方法查询CopyOnWriteArrayList中的数据
public E get(int index) {
// getArray拿到array数组调用get方法的重载
return get(getArray(), index);
}
// 执行get(int)时内部调用的方法
private E get(Object[] a, int index) {
// 直接拿到数组上指定索引位置的值
return (E) a[index];
}
4 写操作
CopyOnWriteArrayList是基于lock锁和副本数组的形式保证线程安全。
// 写入元素不指定索引位置直接放到最后的位置
public boolean add(E e) {
// 获取全局锁并执行lock
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;
// 将副本数组赋值给CopyOnWriteArrayList的原数组
setArray(newElements);
// 添加成功返回true
return true;
} finally {
// 释放锁~
lock.unlock();
}
}
// 写入元素指定索引位置。不会覆盖数据
public void add(int index, E element) {
// 拿锁加锁~
final ReentrantLock lock this.lock;
lock.lock();
try {
// 获取原数组还获取了原数组的长度
Object[] elements getArray();
int len elements.length;
// 如果索引位置大于原数组的长度或者索引位置是小于0的。
if (index len || index 0)
throw new IndexOutOfBoundsException(Index: index
, Size: len);
// 声明了副本数组
Object[] newElements;
// 原数组长度 - 索引位置等到numMovedint numMoved len - index;
// 如果numMoved为0说明数据要放到最后面的位置
if (numMoved 0)
// 直接走了原生态的方式正常复制一份副本数组
newElements Arrays.copyOf(elements, len 1);
else {
// 数组要插入的位置不是最后一个位置
// 副本数组长度依然是原长度 1
newElements new Object[len 1];
// 将原数组从0索引位置开始复制复制到副本数组中的前置位置
System.arraycopy(elements, 0, newElements, 0, index);
// 将原数组从index位置开始复制复制到副本数组的index 1往后放。
// 这时index就空缺出来了。
System.arraycopy(elements, index, newElements, index 1,
numMoved);
}
// 数据正常放到指定的索引位置
newElements[index] element;
// 将副本数组赋值给CopyOnWriteArrayList的原数组
setArray(newElements);
} finally {
// 释放锁
lock.unlock();
}
}