摘要:我们来看下的类继承图可以看到,实现了接口,在多线程进阶二五之框架中,我们提到过实现了接口,以提供和排序相关的功能,维持元素的有序性,所以就是一种为并发环境设计的有序工具类。唯一的区别是针对的仅仅是键值,针对键值对进行操作。
本文首发于一世流云专栏:https://segmentfault.com/blog...一、ConcurrentSkipListSet简介
ConcurrentSkipListSet,是JDK1.6时J.U.C新增的一个集合工具类,顾名思义,它是一种SET类型。
SET类型,在数学上称为“集合”,具有互异性、无序性的特点,也就是说SET中的任意两个元素均不相同(即不包含重复元素),且元素是无序的。
是不是感觉和HashMap有点类似?HashMap中的Key也是不能重复,且是无序的。
事实上,JDK提供的默认SET实现——HashSet,其实就是采用“组合”的方式——内部引用了一个HashMap对象,以此实现SET的功能。
我们来看下ConcurrentSkipListSet的类继承图:
可以看到,ConcurrentSkipListSet实现了NavigableSet接口,在Java多线程进阶(二五)—— J.U.C之collections框架:ConcurrentSkipListMap中,我们提到过ConcurrentSkipListMap实现了NavigableMap接口,以提供和排序相关的功能,维持元素的有序性,所以ConcurrentSkipListSet就是一种为并发环境设计的有序SET工具类。
NavigableSet的功能和NavigableMap几乎是完全一样的,提供了根据指定Key返回最接近项、按升序/降序返回所有键的视图等功能。唯一的区别是NavigableSet针对的仅仅是键值,NavigableMap针对键值对进行操作。二、ConcurrentSkipListSet原理 内部结构
ConcurrentSkipListSet的实现非常简单,其内部引用了一个ConcurrentSkipListMap对象,所有API方法均委托ConcurrentSkipListMap对象完成:
public class ConcurrentSkipListSetextends AbstractSet implements NavigableSet , Cloneable, java.io.Serializable { /** * The underlying map. Uses Boolean.TRUE as value for each * element. This field is declared final for the sake of thread * safety, which entails some ugliness in clone(). */ private final ConcurrentNavigableMap m; public ConcurrentSkipListSet() { m = new ConcurrentSkipListMap (); } public ConcurrentSkipListSet(Comparator super E> comparator) { m = new ConcurrentSkipListMap (comparator); } public ConcurrentSkipListSet(Collection extends E> c) { m = new ConcurrentSkipListMap (); addAll(c); } public ConcurrentSkipListSet(SortedSet s) { m = new ConcurrentSkipListMap (s.comparator()); addAll(s); } ConcurrentSkipListSet(ConcurrentNavigableMap m) { this.m = m; } // ... }
从上述代码可以看出,ConcurrentSkipListSet在构造时创建了一个ConcurrentSkipListMap对象,并由字段m引用,所以其实ConcurrentSkipListSet就是一种跳表类型的数据结构,其平均增删改查的时间复杂度均为O(logn)。
核心方法我们来看下ConcurrentSkipListSet是如何实现API方法的:
public int size() { return m.size(); } public boolean isEmpty() { return m.isEmpty(); } public boolean contains(Object o) { return m.containsKey(o); } public boolean add(E e) { return m.putIfAbsent(e, Boolean.TRUE) == null; } public boolean remove(Object o) { return m.remove(o, Boolean.TRUE); } public void clear() { m.clear(); } //...
从上述代码可以看出,所有操作均是委托ConcurrentSkipListMap对象完成的。重点看下add方法:
public boolean add(E e) { return m.putIfAbsent(e, Boolean.TRUE) == null; }
我们知道ConcurrentSkipListMap对键值对的要求是均不能为null,所以ConcurrentSkipListSet在插入元素的时候,用一个Boolean.TRUE对象(相当于一个值为true的Boolean型对象)作为value,同时putIfAbsent可以保证不会存在相同的Key。
所以,最终跳表中的所有Node结点的Key均不会相同,且值都是Boolean.True。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/76941.html
摘要:同时,也提供了一个基于的实现类,底层基于红黑树设计,是一种有序的。可以看成是并发版本的,但是和不同是,并不是基于红黑树实现的,其底层是一种类似跳表的结构。上述所有构造器都调用了方法方法将一些字段置初始化,然后将指针指向新创建的结点。 showImg(https://segmentfault.com/img/remote/1460000016201159); 本文首发于一世流云专栏:ht...
摘要:整个包,按照功能可以大致划分如下锁框架原子类框架同步器框架集合框架执行器框架本系列将按上述顺序分析,分析所基于的源码为。后,根据一系列常见的多线程设计模式,设计了并发包,其中包下提供了一系列基础的锁工具,用以对等进行补充增强。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首发于一世流云专栏:https...
摘要:仅仅当有多个线程同时进行写操作时,才会进行同步。可以看到,上述方法返回一个迭代器对象,的迭代是在旧数组上进行的,当创建迭代器的那一刻就确定了,所以迭代过程中不会抛出并发修改异常。另外,迭代器对象也不支持修改方法,全部会抛出异常。 showImg(https://segmentfault.com/img/bVbggij?w=960&h=600); 本文首发于一世流云专栏:https://...
摘要:我们之前已经介绍过了,底层基于跳表实现,其操作平均时间复杂度均为。事实上,内部引用了一个对象,以组合方式,委托对象实现了所有功能。线程安全内存的使用较多迭代是对快照进行的,不会抛出,且迭代过程中不支持修改操作。 showImg(https://segmentfault.com/img/bVbggjf?w=600&h=377); 本文首发于一世流云专栏:https://segmentfa...
摘要:接口截止目前为止,我们介绍的阻塞队列都是实现了接口。该类在构造时一般需要指定容量,如果不指定,则最大容量为。另外,由于内部通过来保证线程安全,所以的整体实现时比较简单的。另外,双端队列相比普通队列,主要是多了队尾出队元素队首入队元素的功能。 showImg(https://segmentfault.com/img/bVbgZ7j?w=770&h=514); 本文首发于一世流云专栏:ht...
阅读 1757·2021-11-11 16:55
阅读 2545·2021-08-27 13:11
阅读 3621·2019-08-30 15:53
阅读 2300·2019-08-30 15:44
阅读 1377·2019-08-30 11:20
阅读 1035·2019-08-30 10:55
阅读 941·2019-08-29 18:40
阅读 3028·2019-08-29 16:13