介绍了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);
}

//………………