CopyOnWriteArraySet 源码分析
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 源码分析的更多相关文章
- 死磕 java集合之CopyOnWriteArraySet源码分析——内含巧妙设计
问题 (1)CopyOnWriteArraySet是用Map实现的吗? (2)CopyOnWriteArraySet是有序的吗? (3)CopyOnWriteArraySet是并发安全的吗? (4)C ...
- 【JUC】JDK1.8源码分析之CopyOnWriteArraySet(七)
一.前言 分析完了CopyOnWriteArrayList后,下面接着分析CopyOnWriteArraySet,CopyOnWriteArraySet与CopyOnWriteArrayList有莫大 ...
- 并发-CopyOnWrite源码分析
CopyOnWrite源码分析 参考: https://blog.csdn.net/linsongbin1/article/details/54581787 http://ifeve.com/java ...
- 【JUC】JDK1.8源码分析之ConcurrentSkipListSet(八)
一.前言 分析完了CopyOnWriteArraySet后,继续分析Set集合在JUC框架下的另一个集合,ConcurrentSkipListSet,ConcurrentSkipListSet一个基于 ...
- SOFA 源码分析— 事件总线
前言 大部分框架都是事件订阅功能,即观察者模式,或者叫事件机制.通过订阅某个事件,当触发事件时,回调某个方法.该功能非常的好用,而 SOFA 内部也设计了这个功能,并且内部大量使用了该功能.来看看是如 ...
- 死磕 java集合之ConcurrentSkipListSet源码分析——Set大汇总
问题 (1)ConcurrentSkipListSet的底层是ConcurrentSkipListMap吗? (2)ConcurrentSkipListSet是线程安全的吗? (3)Concurren ...
- CopyOnWriteArrayList源码分析
基于jdk1.7源码 一.无锁容器 CopyOnWriteArrayList是JDK5中添加的新的容器,除此之外,还有CopyOnWriteArraySet.ConcurrentHahshMap和Co ...
- 并发-ConcurrentHashMap源码分析
ConcurrentHashMap 参考: http://www.cnblogs.com/chengxiao/p/6842045.html https://my.oschina.net/hosee/b ...
- Facebook Rebound 弹性动画库 源码分析
Rebound源码分析 让动画不再僵硬:Facebook Rebound Android动画库介绍一文中介绍了rebound这个库. 对于想体验一下rebound的效果,又懒得clone和编译代码的, ...
随机推荐
- pycharm替换文件中所有相同字段方法
1.打开要修改的文件 2.ctrl r调出替换功能,如图所示: 3.上面红框是需要更改的部分,下面红框是想要更改为部分,编辑后,点击“replace all”即可
- 深入浅出《设计模式》之简单工厂模式(C++)
前言 模式介绍 简单工厂模式其实并不属于GoF23(23种设计模式),更类似工厂模式的一种变型.其定义是可以根据参数的不同返回不同类的实例.简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实 ...
- 从未被Google过 #NerverBeenGoogled
我相信大家都用Google搜索互联网上的东西,Google会跟踪你搜索的所有内容,但是你或许不知道,他们也记录着从未被Google过的内容.我有个清单,这些是有史以来从未被Google过的一些东西1. ...
- Git学习笔记1-Git基础
1.创建版本库 $ mkdir /d/learngit #创建空目录 $ cd learngit #进入目录 $ git init #将该目录初始化成Git仓库 2.配置信息 1)配置用户信息: $ ...
- mysql性能优化随笔
mysql性能优化是一个很大的命题,这里只记录一下近期的一些小经验. 曾经以为看了点create table时加index的语法就觉得自己知道怎么做mysql优化了,后来又看了点介绍mysql索引底层 ...
- 201871010118-唐敬博《面向对象程序设计(java)》第十周学习总结
博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...
- 题解:[ZJOI2014]璀灿光华
原题链接 OJ 题号 洛谷 3342 loj 2203 bzoj 3619 题目描述 金先生有一个女朋友没名字.她勤劳勇敢.智慧善良.金先生很喜欢她.为此,金先生用\(a^3\)块\(1 \times ...
- 接口测试Post和Get区别(面试题)
1. HTTP接口传递数据最常用的方式: Get方式是从服务器上获取数据:在做数据查询时,建议用Get方式:如:商品信息接口.搜索接口.博客访客接口等. Post方式是向服务器传送数据 :在做数据添加 ...
- vue.js最最最基础的入门案例
打算自己写一点vue.js从入门到进阶的笔记,方便一些新手从头开始开发的时候,可以参考一下. 写的或许是很简单的文章,提供给新手参考.暂时都是一些入门级别的. 以后会慢慢的加深,进阶,写出一些更好,更 ...
- echars 实现多曲线,多Y轴,曲线单选切换,并且跟随切换指定Y轴
html代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...