一、概述

它是线程安全的无序的集合,可以将它理解成线程安全的HashSet。有意思的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet;但是,HashSet是通过“散列表(HashMap)”实现的,而CopyOnWriteArraySet则是通过“动态数组(CopyOnWriteArrayList)”实现的,并不是散列表。
和CopyOnWriteArrayList类似,CopyOnWriteArraySet具有以下特性:
1. 它最适合于具有以下特征的应用程序:Set 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。
2. 它是线程安全的。
3. 因为通常需要复制整个基础数组,所以可变操作(add()、set() 和 remove() 等等)的开销很大。
4. 迭代器支持hasNext(), next()等不可变操作,但不支持可变 remove()等 操作。
5. 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。

  其实它的结构严格意义来说是一个集合,它的底层实现是利用数组,它的上层实现是CopyOnWriteArrayList。

  其次,CopyOnWriteArraySet是一个集合,所以它是不可以放置重复的元素的,它的取重逻辑是在add中体现的。

  最后,CopyOnWriteArraySet是利用CopyOnWriteArrayList来实现的,因为CopyOnWriteArrayList是线程安全的,所以CopyOnWriteArraySet操作也是线程安全的。

1.1、数据结构

  

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

1.2、示例

/*
* CopyOnWriteArraySet是“线程安全”的集合,而HashSet是非线程安全的。
*
* 下面是“多个线程同时操作并且遍历集合set”的示例
* (01) 当set是CopyOnWriteArraySet对象时,程序能正常运行。
* (02) 当set是HashSet对象时,程序会产生ConcurrentModificationException异常。
*
*/
public class CopyOnWriteArraySetTest1 { // TODO: set是HashSet对象时,程序会出错。
//private static Set<String> set = new HashSet<String>();
private static Set<String> set = new CopyOnWriteArraySet<String>(); public static void main(String[] args) { // 同时启动两个线程对set进行操作!
new MyThread("ta").start();
new MyThread("tb").start();
} private static void printAll() {
String value = null;
Iterator iter = set.iterator();
while (iter.hasNext()) {
value = (String) iter.next();
System.out.print(value + ", ");
}
System.out.println();
} private static class MyThread extends Thread {
MyThread(String name) {
super(name);
} @Override
public void run() {
int i = 0;
while (i++ < 10) {
// “线程名” + "-" + "序号"
String val = Thread.currentThread().getName() + "-" + (i % 6);
set.add(val);
// 通过“Iterator”遍历set。
printAll();
}
}
}
}

1.3、使用场景

二、源码分析

003-多线程-JUC集合-Set-CopyOnWriteArrayList的更多相关文章

  1. java多线程----JUC集合”01之 框架

    java集合的架构.主体内容包括Collection集合和Map类:而Collection集合又可以划分为List(队列)和Set(集合). 1. List的实现类主要有: LinkedList, A ...

  2. JUC集合之 CopyOnWriteArrayList

    CopyOnWriteArrayList介绍 它相当于线程安全的ArrayList.和ArrayList一样,它是个可变数组:但是和ArrayList不同的时,它具有以下特性: 它最适合于具有以下特征 ...

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

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

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

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

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

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

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

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

  7. java多线程系类:JUC集合:01之框架

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

  8. Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap

    概要 本章对Java.util.concurrent包中的ConcurrentSkipListMap类进行详细的介绍.内容包括:ConcurrentSkipListMap介绍ConcurrentSki ...

  9. Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet

    概要 本章对Java.util.concurrent包中的ConcurrentSkipListSet类进行详细的介绍.内容包括:ConcurrentSkipListSet介绍ConcurrentSki ...

  10. Java多线程系列--“JUC集合”07之 ArrayBlockingQueue

    概要 本章对Java.util.concurrent包中的ArrayBlockingQueue类进行详细的介绍.内容包括:ArrayBlockingQueue介绍ArrayBlockingQueue原 ...

随机推荐

  1. nc 命令

    目录 nc 命令 一.简介 二.案例 1.端口扫描 2.聊天 3.文件传输 4.目录传输 5.加密网络发送的数据 6.流视频 7.克隆一个设备 8.打开一个shell 9.反向shell 10.指定端 ...

  2. c# 枚举和位标志

  3. Django中使用xadmin作为后台管理页面

    xadmin后台管理 安装:luffy虚拟环境下 # >: pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2 ...

  4. PAT Basic 1069 微博转发抽奖 (20 分)

    小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包.请你编写程序帮助他确定中奖名单. 输入格式: 输入第一行给出三个正整数 M(≤ 1000). ...

  5. [转载]Java 应用性能调优实践

    Java 应用性能调优实践 Java 应用性能优化是一个老生常谈的话题,笔者根据个人经验,将 Java 性能优化分为 4 个层级:应用层.数据库层.框架层.JVM 层.通过介绍 Java 性能诊断工具 ...

  6. mapbox展示动态图标

    mapbox-gl通过为marker设置css动画,实现动态闪烁效果,先放个效果图 . 1.主要就是为元素设置一个动画, myfirst动画让元素随时间放大 .marker { /* backgrou ...

  7. Educational Codeforces Round 40 (Rated for Div. 2) 954G G. Castle Defense

    题 OvO http://codeforces.com/contest/954/problem/G 解 二分答案, 对于每个二分的答案值 ANS,判断这个答案是否可行. 记 s 数组为题目中描述的 a ...

  8. SIGAI机器学习第六集 决策树

    讲授决策树的基本概念,分类与回归树的原理,决策树的表示能力,决策树的训练算法,寻找最佳分裂的原理,叶子节点值的标记,属性缺失与替 代分裂,决策树的剪枝算法,决策树应用. 非常直观和易于理解的机器学习算 ...

  9. webpack+vue+Eslint+husky+lint-staged 统一项目编码规范

    一. Eslint: 为什么我们要在项目中使用ESLint ESLint可以校验我们写的代码,给代码定义一个规范,项目里的代码必须按照这个规范写. 加入ESLint有非常多的好处,比如说可以帮助我们避 ...

  10. Python—“helloworld”

    接触一门计算机新语言,第一件事就是要准备好一个编译器用来打代码. 网上很多环境搭建的方法,具体参照https://www.runoob.com/python/python-install.html 由 ...