java.util.concurrent;
从 CopyOnWriteArrayList 的名字就能看出它是满足 CopyOnWrite 的 ArrayList,CopyOnWrite 的意思是说,当容器需要被修改的时候,不直接修改当前容器,而是先将当前容器进行 Copy,复制出一个新的容器,然后修改新的容器,完成修改之后,再将原容器的引用指向新的容器。这样就完成了整个修改过程。这样做的好处是,CopyOnWriteArrayList 利用了“不变性”原理,因为容器每次修改都是创建新副本,所以对于旧容器来说,其实是不可变的,也是线程安全的,无需进一步的同步操作。我们可以对 CopyOnWrite 容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素,也不会有修改。
CopyOnWriteArrayList 的所有修改操作(add,set等)都是通过创建底层数组的新副本来实现的,所以 CopyOnWrite 容器也是一种读写分离的思想体现,读和写使用不同的容器。和 ArrayList 不同的是,CopyOnWriteArrayList 的迭代器在迭代的时候,如果数组内容被修改了,CopyOnWriteArrayList 不会报 ConcurrentModificationException 的异常,因为迭代器使用的依然是旧数组,只不过迭代的内容可能已经过时了。
CopyOnWriteArrayList实现了List接口的所有方法,主要包含如下两个成员变量:
// 可重入锁,用于对写操作加锁
final transient ReentrantLock lock = new ReentrantLock();
// Object类型数组,存放数据,volatile修饰,目的是一个线程对这个字段的修改另外一个线程立即可见
private transient volatile Object[] array;
CopyOnWriteArraySet
为线程安全的Set
实现,它是线程安全的无序的集合,可以将它理解成线程安全的HashSet。有意思的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet;但是,HashSet是通过“散列表”实现的,而CopyOnWriteArraySet
则是通过“动态数组(CopyOnWriteArrayList
)”实现的,并不是散列表。
//CopyOnWriteArraySet内部采用CopyOnWriteArrayList存储元素
private final CopyOnWriteArrayList<E> al;
和HashSet
不一样的是,CopyOnWriteArraySet
内部采用CopyOnWriteArrayList
存储元素,这也是CopyOnWriteArraySet
名字的由来,因为CopyOnWriteArrayList
是线程安全的,CopyOnWriteArraySet
的方法都是基于CopyOnWriteArrayList
实现的,所以CopyOnWriteArraySet
自然而然也是线程安全的,同样的,在并发环境下获取数据是弱一致性的。
总结:CopyOnWriteArraySet就是去重的CopyOnWriteArrayList,在项目并发量比较大和读多写少的情况下,并且需要去除重复元素的list的话,可以使用CopyOnWriteArraySet。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。