概述
目录
概述
基本方法以及源码分析
无参构造方法
有参构造方法
set(int index,E element)
add(E e)添加元素至尾部
add(int index, E element)在指定下标添加元素
remove(int index)删除指定下标的元素
removeRange(int fromIndex, int toIndex)删除指定范围的元素
clear()清空集合
addAll(int index, Collection c)在指定位置批量添加元素
概述
CopyOnWriteArrayList是一种线程安全的集合,通过ReentrantLock来实现集合的安全性。当我们对集合进行写入操作时,并不会直接在集合中写入,而是先将当前的集合复制,复制出一个新的集合,在新的集合中进行写入操作,写入 完成后,将原集合的引用指向新的集合。
CopyOnWriteArrayList的设计思想是读写分离,在保证写入操作的安全性时,也不会影响并发读取操作。它的内部使用Object[]数组,允许多线程并发读取,但只有一个线程可以进行写入操作。
基本方法以及源码分析
无参构造方法
//默认的构造方法,数组初始化
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
有参构造方法
// 有参构造方法
public CopyOnWriteArrayList(Collection<? extends E> c) {
Object[] elements;
// copy的集合与当前集合是同一个Class对象
if (c.getClass() == CopyOnWriteArrayList.class)
// 将当前集合强转为CopyOnWriteArrayList并转为数组,存入elements中
elements = ((CopyOnWriteArrayList<?>)c).getArray();
else {
// 直接将当前集合c赋给elements
elements = c.toArray();
// c.toArray might (incorrectly) not return Object[] (see 6260652)
// 数组类型不是Object[]类型,对数组进行复制操作
if (elements.getClass() != Object[].class)
elements = Arrays.copyOf(elements, elements.length, Object[].class);
}
setArray(elements);
}
set(int index,E element)
// 修改指定下标的值
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();
}
}
add(E e)添加元素至尾部
// 添加元素至集合尾部
public boolean add(E e) {
final ReentrantLock lock = this.lock;
// 加锁
lock.lock();
try {
// 得到原数组
Object[] elements = getArray();
int len = elements.length;
// 添加操作复制原数组内容的同时长度+1
Object[] newElements = Arrays.copyOf(elements, len + 1);
// 元素添加至数组尾部
newElements[len] = e;
// 保存新数组(旧数组=>新数组)
setArray(newElements);
return true;
} finally {
// 释放锁
lock.unlock();
}
}
add(int index, E 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)
// 复制原数组,长度加+1
newElements = Arrays.copyOf(elements, len + 1);
else {
// 创建一个新数组,新数组长度=原数组长度+1
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();
}
}
remove(int index)删除指定下标的元素
// 删除指定下标的元素
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;
// 如果=0说明删除的是最后一个元素
if (numMoved == 0)
// 复制原数组长度-1
setArray(Arrays.copyOf(elements, len - 1));
else {
// 创建数组,长度为原数组-1
Object[] newElements = new Object[len - 1];
// 该操作与add(int index, E element)方法同理
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index + 1, newElements, index,
numMoved);
setArray(newElements);
}
return oldValue;
} finally {
// 解锁
lock.unlock();
}
}
removeRange(int fromIndex, int toIndex)删除指定范围的元素
// 删除指定范围的元素
void removeRange(int fromIndex, int toIndex) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
// 判断下标位置是否合理,不合理抛异常
if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
throw new IndexOutOfBoundsException();
// 计算新数组长度
int newlen = len - (toIndex - fromIndex);
// 获取结束下标的位置
int numMoved = len - toIndex;
// =0 ,复制原数组从0到newlen位置
if (numMoved == 0)
setArray(Arrays.copyOf(elements, newlen));
else {
// 新建一个数组,长度为newlen的
Object[] newElements = new Object[newlen];
// 该操作与add(int index, E element)方法同理
System.arraycopy(elements, 0, newElements, 0, fromIndex);
System.arraycopy(elements, toIndex, newElements, fromIndex, numMoved);
setArray(newElements);
}
} finally {
lock.unlock();
}
}
clear()清空集合
// 清空集合中元素
public void clear() {
final ReentrantLock lock = this.lock;
// 加锁
lock.lock();
try {
// 数组初始化
setArray(new Object[0]);
} finally {
lock.unlock();
}
}
addAll(int index, Collection<? extends E> c)在指定位置批量添加元素
// 在指定位置批量添加元素
public boolean addAll(int index, Collection<? extends E> c) {
// 将集合c转换为数组并赋值给cs
Object[] cs = c.toArray();
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);
// 如果集合c为空,则直接返回false
if (cs.length == 0)
return false;
int numMoved = len - index;
Object[] newElements;
// 如果numMoved等于0,则代表在原集合末尾添加
if (numMoved == 0)
// 复制原集合,个数为原集合元素个数加要添加的元素个数
newElements = Arrays.copyOf(elements, len + cs.length);
else {
// 创建新集合
newElements = new Object[len + cs.length];
// 该操作与add(int index, E element)方法同理
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index,
newElements, index + cs.length,
numMoved);
}
// 复制数组至新数组
System.arraycopy(cs, 0, newElements, index, cs.length);
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
最后
以上就是多情大树为你收集整理的CopyOnWriteArrayList源码分析概述基本方法以及源码分析的全部内容,希望文章能够帮你解决CopyOnWriteArrayList源码分析概述基本方法以及源码分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复