CopyOnWriteArraySet  源码分析:

1:数据结构:

private final CopyOnWriteArrayList<E> al; 内部维护的是一个CopyOnWriteArrayList,所以CopyOnWriteArraySet的实现原理是通过CopyOnWriteArrayList的机制来实现的;

2:构造方法:

public CopyOnWriteArraySet() {

al = new CopyOnWriteArrayList<E>();

}

创建一个空的CopyOnWriteArrayList集合,回到CopyOnWriteArrayList中,这个构造方法有两个作用:

1):setArray(new Object[0]); 新建一个长度为0的Object数组,并且赋值给array变量;

2):final transient ReentrantLock lock = new ReentrantLock();实例化一个独占锁对象;

3:方法分析,这里主要分析 add  get remove  这几个常用的方法:

1):addd方法源码分析:

public boolean add(E e) {

return al.addIfAbsent(e);

}

内部调用CopyOnWriteArrayList 的addIfAbsent方法;

下面对addIfAbsent这个方法进行分析:

public boolean addIfAbsent(E e) {   //e=”beppe”

Object[] snapshot = getArray();  // snapshot= Object[0]

return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :

addIfAbsent(e, snapshot);

}

接下来分析indexOf(e, snapshot, 0, snapshot.length) 这个方法:

private static int indexOf(Object o, Object[] elements,

int index, int fence) { //o=”beppe” elements=Object[]

index=0  fence=0

if (o == null) {   //插入空值的场景

for (int i = index; i < fence; i++)

if (elements[i] == null)  //如果集合中之前有 null 元素存在则返回 i

return i;

} else {   //非空值插入场景

for (int i = index; i < fence; i++)

if (o.equals(elements[i]))

return i;

}

return -1;

}

indexOf() 这个方法的作用是判断需要添加的元素在集合中是否存在,若存在则返回该元素的索引,主要用于去重使用;

如果集合中没有重复元素,则返回-1;下面分析addIfAbsent(e, snapshot)这个方法

集合add 首个元素为例:

private boolean addIfAbsent(E e, Object[] snapshot) { //e=”beppe1”  snapshot=Object[0]

final ReentrantLock lock = this.lock;

lock.lock();   //获取独占锁

try {

Object[] current = getArray();  // current=Object[0],当线程并发写入时 获取最新的数组值,这里主要是为了获取最新的数组

int len = current.length;  //len=0

if (snapshot != current) {  //说明这里并发操作

// Optimize for lost race to another addXXX operation

int common = Math.min(snapshot.length, len);

for (int i = 0; i < common; i++)

if (current[i] != snapshot[i] && eq(e, current[i]))

return false;

if (indexOf(e, current, common, len) >= 0)

return false;

}

//对数组进行动态扩容  copy 当前数组到 新数组中

Object[] newElements = Arrays.copyOf(current, len + 1);

//将新元素赋值到新的数组中

newElements[len] = e;

setArray(newElements);

return true;

} finally {

lock.unlock();   //解锁

}

}

4:remove方法:

public boolean remove(Object o) {

return al.remove(o);   // al 是一个CopyOnWriteArrayList 对象,这里就是执行CopyOnWriteArrayList的remove方法

}

public boolean remove(Object o) {

Object[] snapshot = getArray();

int index = indexOf(o, snapshot, 0, snapshot.length);

return (index < 0) ? false : remove(o, snapshot, index);

}

说明:CopyOnWriteArraySet 内部维护的是一个 CopyOnWriteArrayList 数据结构,其原理和CopyOnWriteArrayList 的实现原理是一致的;

CopyOnWriteArraySet 源码分析的更多相关文章

  1. 死磕 java集合之CopyOnWriteArraySet源码分析——内含巧妙设计

    问题 (1)CopyOnWriteArraySet是用Map实现的吗? (2)CopyOnWriteArraySet是有序的吗? (3)CopyOnWriteArraySet是并发安全的吗? (4)C ...

  2. 【JUC】JDK1.8源码分析之CopyOnWriteArraySet(七)

    一.前言 分析完了CopyOnWriteArrayList后,下面接着分析CopyOnWriteArraySet,CopyOnWriteArraySet与CopyOnWriteArrayList有莫大 ...

  3. 并发-CopyOnWrite源码分析

    CopyOnWrite源码分析 参考: https://blog.csdn.net/linsongbin1/article/details/54581787 http://ifeve.com/java ...

  4. 【JUC】JDK1.8源码分析之ConcurrentSkipListSet(八)

    一.前言 分析完了CopyOnWriteArraySet后,继续分析Set集合在JUC框架下的另一个集合,ConcurrentSkipListSet,ConcurrentSkipListSet一个基于 ...

  5. SOFA 源码分析— 事件总线

    前言 大部分框架都是事件订阅功能,即观察者模式,或者叫事件机制.通过订阅某个事件,当触发事件时,回调某个方法.该功能非常的好用,而 SOFA 内部也设计了这个功能,并且内部大量使用了该功能.来看看是如 ...

  6. 死磕 java集合之ConcurrentSkipListSet源码分析——Set大汇总

    问题 (1)ConcurrentSkipListSet的底层是ConcurrentSkipListMap吗? (2)ConcurrentSkipListSet是线程安全的吗? (3)Concurren ...

  7. CopyOnWriteArrayList源码分析

    基于jdk1.7源码 一.无锁容器 CopyOnWriteArrayList是JDK5中添加的新的容器,除此之外,还有CopyOnWriteArraySet.ConcurrentHahshMap和Co ...

  8. 并发-ConcurrentHashMap源码分析

    ConcurrentHashMap 参考: http://www.cnblogs.com/chengxiao/p/6842045.html https://my.oschina.net/hosee/b ...

  9. Facebook Rebound 弹性动画库 源码分析

    Rebound源码分析 让动画不再僵硬:Facebook Rebound Android动画库介绍一文中介绍了rebound这个库. 对于想体验一下rebound的效果,又懒得clone和编译代码的, ...

随机推荐

  1. python numba讲解

    目录 一:什么是numba 二:如何使用numba   由于python有动态解释性语言的特性,跑起代码来相比java.c++要慢很多,尤其在做科学计算的时候,十亿百亿级别的运算,让python的这种 ...

  2. 命令 docker rm | docker rmi | docker prune 的差异

    区别: docker rm : 删除一个或多个 容器 docker rmi : 删除一个或多个 镜像 docker prune : 用来删除不再使用的 docker 对象 一.docker rm 命令 ...

  3. 从webkit内核简单看css样式和css规则优先级(权重)

    目录 webkit中样式相关类及类间关系 样式规则匹配 权重(优先级)计算 权重相同时的覆盖原则 webkit中样式相关类及类间关系 资料来源: <webkit技术内幕> 结构相关类: 1 ...

  4. Ubuntu19.04安装常用软件

    安装Indicator Stickynotes 桌面便签小工具sudo add-apt-repository ppa:umang/indicator-stickynotessudo apt-get u ...

  5. 对cell每一行做标记

    通过数组进行标记 初始化列表的时候给一个值如 for (int i = 0; i < [self.tableData count]; i++)    {        [_allOrderBoo ...

  6. iOS 快速打包方法

    这种打包方式应该是目前所有打包方式中最快的,就是编译工程--找到.app文件--新建Payload文件夹--拷贝.app到Payload文件夹--压缩成zip--更改后缀名为ipa--完成! 注意事项 ...

  7. 数据库MySQL学习笔记高级篇

    数据库MySQL学习笔记高级篇 写在前面 学习链接:数据库 MySQL 视频教程全集 1. mysql的架构介绍 mysql简介 概述 高级Mysql 完整的mysql优化需要很深的功底,大公司甚至有 ...

  8. day 34 作业

    作业 mysql> create table tea( -> id int unsigned auto_increment primary key, -> name varchar( ...

  9. static、const、extern等关键字

    static 参考:https://blog.csdn.net/guotianqing/article/details/79828100 http://c.biancheng.net/view/222 ...

  10. jq中

    1.jquery位置信息 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...