介绍了JDK1.8的CopyOnWriteArraySet的特性和源码实现!
文章目录
- 1 CopyOnWriteArraySet的概述
- 2 CopyOnWriteArraySet的源码
- 2.1 基本结构
- 2.2 API方法
1 CopyOnWriteArraySet的概述
public class CopyOnWriteArraySet< E >
extends AbstractSet< E >
implements Serializable
前面的文章讲了CopyOnWriteArrayList的原理,实际上在JUC中还存在一个“完全依靠”CopyOnWriteArrayList实现的并发容器,那就是CopyOnWriteArraySet。
CopyOnWriteArraySet同样来自于JDK1.5。虽然名字带有Set,并且CopyOnWriteArraySet和HashSet都继承于共同的父类AbstractSet,但是它们有很大的不同。HashSet内部包装了一个HashMap,本质是一个Map(散列表),但是CopyOnWriteArraySet内部包装的是一个CopyOnWriteArrayList,因此本质是一个List(数组)。
那为什么命名中带有“Set”呢?因为CopyOnWriteArraySet带有一系列Set集合的特性。
CopyOnWriteArraySet不能添加重复元素,但是插入成功的元素是有序的。实际上它的add方法内部就是调用CopyOnWriteArrayList的addIfAbsent方法!
没有类似于List集合那样的一系列通过索引操作元素的方法,比如:get(int index),add(int index,E e),set(int index,E e),remove(int index))等方法。
看懂了CopyOnWriteArrayList的源码,你就看懂了CopyOnWriteArraySet的源码:JUC—CopyOnWriteArrayList源码深度解析。
2 CopyOnWriteArraySet的源码
2.1 基本结构
我们说过CopyOnWriteArraySet内部具有一个CopyOnWriteArrayList。因为它的构造器实际上是初始化了一个CopyOnWriteArraySet。这类似于装饰设计模式。
/**
* 底层使用的就是一个CopyOnWriteArrayList实例,具有一个全局变量
*/
private final CopyOnWriteArrayList<E> al;
/**
* 空构造器,可以看出调用了CopyOnWriteArrayList的空构造器
*/
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>();
}
/**
* 按照集合的迭代器返回的顺序创建一个包含指定集合元素的列表。如果指定的集合为null,则抛出NullPointerException。
*
* @param c 指定集合
*/
public CopyOnWriteArraySet(Collection<? extends E> c) {
/*如果指定集合类型是否就是CopyOnWriteArraySet类型*/
if (c.getClass() == CopyOnWriteArraySet.class) {
//如果是,那么强转为CopyOnWriteArraySet
@SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
(CopyOnWriteArraySet<E>) c;
//调用CopyOnWriteArrayList的带参构造器
al = new CopyOnWriteArrayList<E>(cc.al);
}
/*否则*/
else {
//新建一个CopyOnWriteArrayList
al = new CopyOnWriteArrayList<E>();
//调用addAllAbsent方法
al.addAllAbsent(c);
}
}
2.2 API方法
API方法都是通过内部的CopyOnWriteArrayList的方法来进行代理调用的,非常简单。这些方法的源码我们在CopyOnWriteArrayList的部分已经都讲解过了。
因此CopyOnWriteArraySet同样写操作需要加锁,效率很低;读操作不需要加锁,效率很高,CopyOnWriteArraySet同样适用读多写少的情况。
读操作具有弱一致性,只能保证数据的最终一致性。迭代器是fail-safe的,不会抛出ConcurrentModificationException异常,但也不支持写操作。
public boolean add(E e) {
//调用addIfAbsent方法
return al.addIfAbsent(e);
}
public boolean addAll(Collection<? extends E> c) {
//调用addAllAbsent方法
return al.addAllAbsent(c) > 0;
}
public void clear() {
//调用clear方法
al.clear();
}
public boolean contains(Object o) {
//调用contains方法
return al.contains(o);
}
public boolean remove(Object o) {
//调用remove方法
return al.remove(o);
}
//………………