摘要:我们之前已经介绍过了,底层基于跳表实现,其操作平均时间复杂度均为。事实上,内部引用了一个对象,以组合方式,委托对象实现了所有功能。线程安全内存的使用较多迭代是对快照进行的,不会抛出,且迭代过程中不支持修改操作。
本文首发于一世流云专栏:https://segmentfault.com/blog...一、CopyOnWriteArraySet简介
CopyOnWriteArraySet,是另一类适合并发环境的SET工具类,也是在JDK1.5时,随着J.U.C包一起引入的。
我们之前已经介绍过了ConcurrentSkipListSet,ConcurrentSkipListSet底层基于Skip List(跳表)实现,其操作平均时间复杂度均为O(logn)。
CopyOnWriteArraySet,从名字上可以看出,也是基于“写时复制”的思想。事实上,CopyOnWriteArraySet内部引用了一个CopyOnWriteArrayList对象,以“组合”方式,委托CopyOnWriteArrayList对象实现了所有API功能。
public class CopyOnWriteArraySet二、CopyOnWriteArraySet原理extends AbstractSet implements java.io.Serializable { private final CopyOnWriteArrayList al; /** * Creates an empty set. */ public CopyOnWriteArraySet() { al = new CopyOnWriteArrayList (); } public CopyOnWriteArraySet(Collection extends E> c) { if (c.getClass() == CopyOnWriteArraySet.class) { CopyOnWriteArraySet cc = (CopyOnWriteArraySet ) c; al = new CopyOnWriteArrayList (cc.al); } else { al = new CopyOnWriteArrayList (); al.addAllAbsent(c); } } // ... }
我们来看下CopyOnWriteArraySet是如何实现API接口的功能的:
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(); } publicT[] toArray(T[] a) { return al.toArray(a); } public void clear() { al.clear(); } public boolean remove(Object o) { return al.remove(o); } 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) > 0; } public boolean removeAll(Collection> c) { return al.removeAll(c); } public boolean retainAll(Collection> c) { return al.retainAll(c); } public Iterator iterator() { return al.iterator(); } public boolean removeIf(Predicate super E> filter) { return al.removeIf(filter); } public void forEach(Consumer super E> action) { al.forEach(action); }
可以看到,上述所有的方法都是通过委托实现的,唯一的区别就是CopyOnWriteArraySet不允许含有重复元素,所以添加元素(add方法)时,内部调用了CopyOnWriteArrayList的addAllAbsent方法。
三、总结既然CopyOnWriteArraySet也是基于“写时复制”的思想,那么它的特性也和CopyOnWriteArrayList是类似的,归结起来,有以下几点:
适合“读多写少”且数据量不大的场景。
线程安全
内存的使用较多
迭代是对快照进行的,不会抛出ConcurrentModificationException,且迭代过程中不支持修改操作。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/76939.html
摘要:仅仅当有多个线程同时进行写操作时,才会进行同步。可以看到,上述方法返回一个迭代器对象,的迭代是在旧数组上进行的,当创建迭代器的那一刻就确定了,所以迭代过程中不会抛出并发修改异常。另外,迭代器对象也不支持修改方法,全部会抛出异常。 showImg(https://segmentfault.com/img/bVbggij?w=960&h=600); 本文首发于一世流云专栏:https://...
摘要:整个包,按照功能可以大致划分如下锁框架原子类框架同步器框架集合框架执行器框架本系列将按上述顺序分析,分析所基于的源码为。后,根据一系列常见的多线程设计模式,设计了并发包,其中包下提供了一系列基础的锁工具,用以对等进行补充增强。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首发于一世流云专栏:https...
摘要:我们来看下的类继承图可以看到,实现了接口,在多线程进阶二五之框架中,我们提到过实现了接口,以提供和排序相关的功能,维持元素的有序性,所以就是一种为并发环境设计的有序工具类。唯一的区别是针对的仅仅是键值,针对键值对进行操作。 showImg(https://segmentfault.com/img/bVbggic?w=960&h=600); 本文首发于一世流云专栏:https://seg...
摘要:接口截止目前为止,我们介绍的阻塞队列都是实现了接口。该类在构造时一般需要指定容量,如果不指定,则最大容量为。另外,由于内部通过来保证线程安全,所以的整体实现时比较简单的。另外,双端队列相比普通队列,主要是多了队尾出队元素队首入队元素的功能。 showImg(https://segmentfault.com/img/bVbgZ7j?w=770&h=514); 本文首发于一世流云专栏:ht...
摘要:在章节中,我们说过,维护了一把全局锁,无论是出队还是入队,都共用这把锁,这就导致任一时间点只有一个线程能够执行。入队锁对应的是条件队列,出队锁对应的是条件队列,所以每入队一个元素,应当立即去唤醒可能阻塞的其它入队线程。 showImg(https://segmentfault.com/img/bVbgCD9?w=1920&h=1080); 本文首发于一世流云专栏:https://seg...
阅读 1136·2021-11-24 09:39
阅读 2631·2021-09-28 09:35
阅读 989·2019-08-30 15:55
阅读 1311·2019-08-30 15:44
阅读 846·2019-08-29 17:00
阅读 1931·2019-08-29 12:19
阅读 3280·2019-08-28 18:28
阅读 650·2019-08-28 18:10