转载:http://www.cnblogs.com/skywang12345/p/3498497.html

概要

本章是JUC系列中的CopyOnWriteArraySet篇。接下来,会先对CopyOnWriteArraySet进行基本介绍,然后再说明它的原理,接着通过代码去分析,最后通过示例更进一步的了解CopyOnWriteArraySet。内容包括:
CopyOnWriteArraySet介绍
CopyOnWriteArraySet原理和数据结构
CopyOnWriteArraySet函数列表
CopyOnWriteArraySet源码

CopyOnWriteArraySet介绍

它是线程安全的无序的集合,可以将它理解成线程安全的HashSet。有意思的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet;但是,HashSet是通过“散列表(HashMap)”实现的,而CopyOnWriteArraySet则是通过“动态数组(CopyOnWriteArrayList)”实现的,并不是散列表。
和CopyOnWriteArrayList类似,其实CopyOnWriteSet底层包含一个CopyOnWriteList,几乎所有操作都是借助CopyOnWriteList,就像HashSet包含HashMap

CopyOnWriteArraySet具有以下特性:
1. 它最适合于具有以下特征的应用程序:Set 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。
2. 它是线程安全的。
3. 因为通常需要复制整个基础数组,所以可变操作(add()、set() 和 remove() 等等)的开销很大。
4. 迭代器支持hasNext(), next()等不可变操作,但不支持可变 remove()等 操作。
5. 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。

CopyOnWriteArraySet原理和数据结构

CopyOnWriteArraySet的数据结构,如下图所示:

说明
  1. CopyOnWriteArraySet继承于AbstractSet,这就意味着它是一个集合。
  2. CopyOnWriteArraySet包含CopyOnWriteArrayList对象,它是通过CopyOnWriteArrayList实现的。而CopyOnWriteArrayList本质是个动态数组队列,
所以CopyOnWriteArraySet相当于通过通过动态数组实现的“集合”! CopyOnWriteArrayList中允许有重复的元素;但是,CopyOnWriteArraySet是一个集合,所以它不能有重复集合。因此,CopyOnWriteArrayList额外提供了addIfAbsent()和addAllAbsent()这两个添加元素的API,通过这些API来添加元素时,只有当元素不存在时才执行添加操作!
   至于CopyOnWriteArraySet的“线程安全”机制,和CopyOnWriteArrayList一样,是通过volatile和互斥锁来实现的。这个在前一章节介绍CopyOnWriteArrayList时数据结构时,已经进行了说明,这里就不再重复叙述了。

CopyOnWriteArraySet函数列表

// 创建一个空 set。
CopyOnWriteArraySet()
// 创建一个包含指定 collection 所有元素的 set。
CopyOnWriteArraySet(Collection<? extends E> c) // 如果指定元素并不存在于此 set 中,则添加它。
boolean add(E e)
// 如果此 set 中没有指定 collection 中的所有元素,则将它们都添加到此 set 中。
boolean addAll(Collection<? extends E> c)
// 移除此 set 中的所有元素。
void clear()
// 如果此 set 包含指定元素,则返回 true。
boolean contains(Object o)
// 如果此 set 包含指定 collection 的所有元素,则返回 true。
boolean containsAll(Collection<?> c)
// 比较指定对象与此 set 的相等性。
boolean equals(Object o)
// 如果此 set 不包含任何元素,则返回 true。
boolean isEmpty()
// 返回按照元素添加顺序在此 set 中包含的元素上进行迭代的迭代器。
Iterator<E> iterator()
// 如果指定元素存在于此 set 中,则将其移除。
boolean remove(Object o)
// 移除此 set 中包含在指定 collection 中的所有元素。
boolean removeAll(Collection<?> c)
// 仅保留此 set 中那些包含在指定 collection 中的元素。
boolean retainAll(Collection<?> c)
// 返回此 set 中的元素数目。
int size()
// 返回一个包含此 set 所有元素的数组。
Object[] toArray()
// 返回一个包含此 set 所有元素的数组;返回数组的运行时类型是指定数组的类型。
<T> T[] toArray(T[] a)

CopyOnWriteArraySet源码(JDK1.8版本)

CopyOnWriteArraySet.java的完整源码如下:

 public class CopyOnWriteArraySet<E> extends AbstractSet<E>
implements java.io.Serializable {
private static final long serialVersionUID = 5457747651344034263L; private final CopyOnWriteArrayList<E> al; /**
* Creates an empty set.
*/
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>();
} /
public CopyOnWriteArraySet(Collection<? extends E> c) {
if (c.getClass() == CopyOnWriteArraySet.class) {
@SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
(CopyOnWriteArraySet<E>)c;
al = new CopyOnWriteArrayList<E>(cc.al);
}
else {
al = new CopyOnWriteArrayList<E>();
al.addAllAbsent(c);
}
} public int size() {
return al.size();
} public boolean isEmpty() {
return al.isEmpty();
} public boolean contains(Object o) {
return al.contains(o);
} public Object[] toArray() {
return al.toArray();
} public <T> T[] toArray(T[] a) {
return al.toArray(a);
} public void clear() {
al.clear();
} public boolean remove(Object o) {
return al.remove(o);
}

//这里添加时,为了避免重复元素,调用的不是CopyOnWriteList的add方法,而是另外一个去重的方法
public boolean add(E e) {
return al.addIfAbsent(e);
}
public boolean containsAll(Collection<?> c) {
return al.containsAll(c);
} public boolean addAll(Collection<? extends E> c) {
return al.addAllAbsent(c) > ;
} public boolean removeAll(Collection<?> c) {
return al.removeAll(c);
} public boolean retainAll(Collection<?> c) {
return al.retainAll(c);
} public Iterator<E> iterator() {
return al.iterator();
} public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Set<?> set = (Set<?>)(o);
Iterator<?> it = set.iterator(); // Uses O(n^2) algorithm that is only appropriate
// for small sets, which CopyOnWriteArraySets should be. // Use a single snapshot of underlying array
Object[] elements = al.getArray();
int len = elements.length;
// Mark matched elements to avoid re-checking
boolean[] matched = new boolean[len];
int k = ;
outer: while (it.hasNext()) {
if (++k > len)
return false;
Object x = it.next();
for (int i = ; i < len; ++i) {
if (!matched[i] && eq(x, elements[i])) {
matched[i] = true;
continue outer;
}
}
return false;
}
return k == len;
} public boolean removeIf(Predicate<? super E> filter) {
return al.removeIf(filter);
} public void forEach(Consumer<? super E> action) {
al.forEach(action);
} public Spliterator<E> spliterator() {
return Spliterators.spliterator
(al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
} /**
* Tests for equality, coping with nulls.
*/
private static boolean eq(Object o1, Object o2) {
return (o1 == null) ? o2 == null : o1.equals(o2);
}
}

CopyOnWriteArraySet是通过CopyOnWriteArrayList实现的,它的API基本上都是通过调用CopyOnWriteArrayList的API来实现的。相信对CopyOnWriteArrayList了解的话,对CopyOnWriteArraySet的了解是水到渠成的事;所以,这里就不再对CopyOnWriteArraySet的代码进行详细的解析了。

Java多线程系列--CopyOnWriteArraySet的更多相关文章

  1. Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet

    概要 本章是JUC系列中的CopyOnWriteArraySet篇.接下来,会先对CopyOnWriteArraySet进行基本介绍,然后再说明它的原理,接着通过代码去分析,最后通过示例更进一步的了解 ...

  2. Java多线程系列目录(共43篇)

    最近,在研究Java多线程的内容目录,将其内容逐步整理并发布. (一) 基础篇 01. Java多线程系列--“基础篇”01之 基本概念 02. Java多线程系列--“基础篇”02之 常用的实现多线 ...

  3. Java多线程系列--“JUC集合”01之 框架

    概要 之前,在"Java 集合系列目录(Category)"中,讲解了Java集合包中的各个类.接下来,将展开对JUC包中的集合进行学习.在学习之前,先温习一下"Java ...

  4. Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList

    概要 本章是"JUC系列"的CopyOnWriteArrayList篇.接下来,会先对CopyOnWriteArrayList进行基本介绍,然后再说明它的原理,接着通过代码去分析, ...

  5. Java多线程系列--“JUC集合”04之 ConcurrentHashMap

    概要 本章是JUC系列的ConcurrentHashMap篇.内容包括:ConcurrentHashMap介绍ConcurrentHashMap原理和数据结构ConcurrentHashMap函数列表 ...

  6. Java多线程系列

    一.参考文献 1.:Java多线程系列目录 (一) 基础篇 01. Java多线程系列--“基础篇”01之 基本概念 02. Java多线程系列--“基础篇”02之 常用的实现多线程的两种方式 03. ...

  7. Java多线程系列目录(转)

    转载方便自己学习,转自:Java多线程系列目录(共43篇) http://www.cnblogs.com/skywang12345/p/java_threads_category.html 最近,在研 ...

  8. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  9. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

随机推荐

  1. [ActionScript 3.0] 透视投影

    下面的示例演示如何使用透视投影来创建 3D 空间.该示例演示如何通过projectionCenter属性来修改消失点和更改空间的透视投影.进行这种修改后,将强制重新计算focalLength和fiel ...

  2. Hello QT(译)

    简评:PySide2 是 QT 官方出品,值得期待 PySide2 第一个技术预览版快要发布了,在此给出一个简单的例子,来展示它将如何打开 Python世界的大门. 下面我们将使用 QWidgets ...

  3. Intellig IDEA 搭建spring boot 热部署

    在pom中直接引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...

  4. .net core 2.0部署到CentOS7系统

    1.Nginx的安装(重启Nginx命令: systemctl restart nginx) 输入命令( 根据提示输入Y 即可): sudo yum install epel-release sudo ...

  5. [原创] Shell 参数传递 与 默认值

    目录 简介 基本传参 $* 与 $@ 区别 默认参数(变量默认值) if 繁琐方式 - 变量为null = 变量为null时, 同时改变变量值 :- 变量为null 或 空字符串 := 变量为null ...

  6. C# 文件读写Helper类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  7. 「框架」菜鸟简单模仿一下spring的ioc和aop思想,欢迎大家进来阅读指教

    *博客搬家:初版发布于 2015/12/04 16:41    原博客地址:https://my.oschina.net/sunqinwen/blog/539397 spring最核心的部分莫过于io ...

  8. 认识CSS中高级技巧之元素的显示与隐藏

    前端之HTML,CSS(八) CSS高级技巧 元素的显示与隐藏 CSS中有三个属性可以设置元素的显示于隐藏,分别是:display.visibility和overflow. display 隐藏元素: ...

  9. element-ui table多选CheckBox参数解析

    element-UI里的table表格与多选框CheckBox的组合很常用,官网也给了很多参数,自己总结了一下,方便日后使用 1.简易用法,没有附加的功能 要在表格里使用CheckBox很简单,只需设 ...

  10. 原子操作类AtomicInteger详解

    为什么需要AtomicInteger原子操作类?对于Java中的运算操作,例如自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的.num++解析为num=num+1,明显,这个操作不 ...