Java CopyOnWriteArraySet源码深度解析

介绍了JDK1.8的CopyOnWriteArraySet的特性和源码实现!

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);
}

//………………

相关文章:

  1. JUC—CopyOnWriteArrayList源码深度解析

如果有什么不懂或者需要交流,可以留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值