Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
来源:互联网 发布:linux 自动启动服务 编辑:程序博客网 时间:2024/06/18 14:09
概要
本章是JUC系列中的CopyOnWriteArraySet篇。接下来,会先对CopyOnWriteArraySet进行基本介绍,然后再说明它的原理,接着通过代码去分析,最后通过示例更进一步的了解CopyOnWriteArraySet。内容包括:
CopyOnWriteArraySet介绍
CopyOnWriteArraySet原理和数据结构
CopyOnWriteArraySet函数列表
CopyOnWriteArraySet源码(JDK1.7.0_40版本)
CopyOnWriteArraySet示例
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3498497.html
CopyOnWriteArraySet介绍
它是线程安全的无序的集合,可以将它理解成线程安全的HashSet。有意思的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet;但是,HashSet是通过“散列表(HashMap)”实现的,而CopyOnWriteArraySet则是通过“动态数组(CopyOnWriteArrayList)”实现的,并不是散列表。
和CopyOnWriteArrayList类似,CopyOnWriteArraySet具有以下特性:
1. 它最适合于具有以下特征的应用程序:Set 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。
2. 它是线程安全的。
3. 因为通常需要复制整个基础数组,所以可变操作(add()、set() 和 remove() 等等)的开销很大。
4. 迭代器支持hasNext(), next()等不可变操作,但不支持可变 remove()等 操作。
5. 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。
建议:在学习CopyOnWriteArraySet之前,先通过"Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例"对HashSet进行了解。
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.7.0_40版本)
CopyOnWriteArraySet.java的完整源码如下:
CopyOnWriteArraySet是通过CopyOnWriteArrayList实现的,它的API基本上都是通过调用CopyOnWriteArrayList的API来实现的。相信对CopyOnWriteArrayList了解的话,对CopyOnWriteArraySet的了解是水到渠成的事;所以,这里就不再对CopyOnWriteArraySet的代码进行详细的解析了。若对CopyOnWriteArrayList不了解,请参考“Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList”。
CopyOnWriteArraySet示例
下面,我们通过一个例子去对比HashSet和CopyOnWriteArraySet。
import java.util.*;import java.util.concurrent.*;/* * CopyOnWriteArraySet是“线程安全”的集合,而HashSet是非线程安全的。 * * 下面是“多个线程同时操作并且遍历集合set”的示例 * (01) 当set是CopyOnWriteArraySet对象时,程序能正常运行。 * (02) 当set是HashSet对象时,程序会产生ConcurrentModificationException异常。 * * @author skywang */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(); } } }}
(某一次)运行结果:
ta-1, tb-1, ta-1, tb-1, ta-1, tb-1, ta-1, ta-2, tb-1, ta-1, ta-2, tb-1, tb-2, ta-2, ta-1, tb-2, tb-1, ta-3, ta-2, ta-1, tb-2, tb-1, ta-3, ta-2, tb-3, tb-2, ta-1, ta-3, tb-1, tb-3, ta-2, ta-4, tb-2, ta-1, ta-3, tb-1, tb-3, ta-2, ta-4, tb-2, tb-4, ta-3, ta-1, tb-3, tb-1, ta-4, ta-2, tb-4, tb-2, ta-5, ta-3, ta-1, tb-3, tb-1, ta-4, ta-2, tb-4, tb-2, ta-5, ta-3, tb-5, tb-3, ta-1, ta-4, tb-1, tb-4, ta-2, ta-5, tb-2, tb-5, ta-3, ta-0, tb-3, ta-1, ta-4, tb-1, tb-4, ta-2, ta-5, tb-2, tb-5, ta-3, ta-0, tb-3, tb-0, ta-4, ta-1, tb-4, tb-1, ta-5, ta-2, tb-5, tb-2, ta-0, ta-3, tb-0, tb-3, ta-1, ta-4, tb-1, tb-4, ta-2, ta-5, tb-5, ta-0, tb-0, ta-1, tb-2, tb-1, ta-3, ta-2, tb-3, tb-2, ta-4, ta-3, tb-4, tb-3, ta-5, ta-4, tb-5, tb-4, ta-0, ta-5, tb-0, tb-5, ta-1, ta-0, tb-1, tb-0, ta-2, ta-1, tb-2, tb-1, ta-3, ta-2, tb-3, tb-2, ta-4, ta-3, tb-4, tb-3, ta-5, tb-5, ta-0, tb-0, ta-4, ta-1, tb-4, tb-1, ta-5, ta-2, tb-5, tb-2, ta-0, ta-3, tb-0, tb-3, ta-1, ta-4, tb-1, tb-4, ta-2, ta-5, tb-2, tb-5, ta-3, ta-0, tb-3, tb-0, ta-4, tb-4, ta-5, tb-5, ta-0, tb-0,
结果说明:
由于set是集合对象,因此它不会包含重复的元素。
如果将源码中的set改成HashSet对象时,程序会产生ConcurrentModificationException异常。
更多内容
1. Java多线程系列--“JUC集合”01之 框架
2. Java多线程系列--“JUC集合”02之 CopyOnWriteArrayLis
3. Java多线程系列目录(共xx篇)
4. Java 集合系列目录(Category)
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- JUC集合-03之 CopyOnWriteArraySet
- Java多线程”JUC”集合中的CopyOnWriteArraySet
- Java多线程系列--“JUC集合”
- Java多线程系列--“JUC集合”04之 ConcurrentHashMap
- Java多线程系列--“JUC集合”01之 框架
- Java多线程系列--“JUC集合”01之 框架
- Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
- Java多线程系列--“JUC集合”04之 ConcurrentHashMap
- Java多线程系列--“JUC集合”01之 框架
- Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
- Java多线程系列--“JUC集合”04之 ConcurrentHashMap
- Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap
- Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet
- A Closer Look At Hub, Switch And Router
- Kotlin中的“==”和“===”
- python 操作mysql数据库
- web前端的一些小知识
- Entity Framework中的字符串插值引发担忧
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
- ASP.NET Core 运行原理剖析
- WebSocket In ASP.NET Core(二)
- asp.net core AuthenticationMiddleware 在WebApi中的的使用
- Configuration Extensions
- 手把手教你使用spring cloud+dotnet core搭建微服务架构:服务治理(-)
- 为什么你需要将代码迁移到ASP.NET Core 2.0?
- 基于Office 365的随需应变业务应用平台
- 跨平台应用集成(在ASP.NET Core MVC 应用程序中集成 Microsoft Graph)