【Java多线程之ConcurrentSkipListMap深入分析】

一、前言

  concurrentHashMap与ConcurrentSkipListMap性能测试

  在4线程1.6万数据的条件下,ConcurrentHashMap 存取速度是ConcurrentSkipListMap 的4倍左右。

  但ConcurrentSkipListMap有几个ConcurrentHashMap 不能比拟的优点:

  1、ConcurrentSkipListMap 的key是有序的。

  2、ConcurrentSkipListMap 支持更高的并发。ConcurrentSkipListMap 的存取时间是log(N),和线程数几乎无关。也就是说在数据量一定的情况下,并发的线程越多,ConcurrentSkipListMap越能体现出他的优势。

  二、使用建议

  在非多线程的情况下,应当尽量使用TreeMap.此外对于并发性相对较低的并行程序可以使用Collections.synchronizedSortedMap将TreeMap进行包装,也可以提供较好的效率。对于高并发程序,应当使用ConcurrentSkipListMap,能够提供更高的并发度。

  所以在多线程程序中,如果需要对Map的键值进行排序时,请尽量使用ConcurrentSkipListMap,可能得到更好的并发度。

  注意,调用ConcurrentSkipListMap的size时,由于多个线程可以同时对映射表进行操作,所以映射表需要遍历整个链表才能返回元素个数,这个操作是个O(log(n))的操作。

  二、什么是SkipList

  Skip list(跳表)是一种可以代替平衡树的数据结构,默认是按照Key值升序的。Skip list让已排序的数据分布在多层链表中,以0-1随机数决定一个数据的向上攀升与否,通过"空间来换取时间"的一个算法,在每个节点中增加了向前的指针,在插入、删除、查找时可以忽略一些不可能涉及到的结点,从而提高了效率。

  从概率上保持数据结构的平衡比显示的保持数据结构平衡要简单的多。对于大多数应用,用Skip list要比用树算法相对简单。由于Skip list比较简单,实现起来会比较容易,虽然和平衡树有着相同的时间复杂度(O(logn)),但是skip list的常数项会相对小很多。Skip list在空间上也比较节省。一个节点平均只需要1.333个指针(甚至更少)。

  图1-1 Skip list结构图(以7,14,21,32,37,71,85序列为例)

  Skip list的性质

  (1) 由很多层结构组成,level是通过一定的概率随机产生的。

  (2) 每一层都是一个有序的链表,默认是升序,也可以根据创建映射时所提供的Comparator进行排序,具体取决于使用的构造方法。

  (3) 最底层(Level 1)的链表包含所有元素。

  (4) 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现。

  (5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

  三、什么是ConcurrentSkipListMap

  ConcurrentSkipListMap提供了一种线程安全的并发访问的排序映射表。内部是SkipList(跳表)结构实现,在理论上能够在O(log(n))时间内完成查找、插入、删除操作。

  注意,调用ConcurrentSkipListMap的size时,由于多个线程可以同时对映射表进行操作,所以映射表需要遍历整个链表才能返回元素个数,这个操作是个O(log(n))的操作。

  ConcurrentSkipListMap存储结构

   \
  ConcurrentSkipListMap存储结构图

  跳跃表(SkipList):(如上图所示)

  1.多条链构成,是关键字升序排列的数据结构;

  2.包含多个级别,一个head引用指向最高的级别,最低(底部)的级别,包含所有的key;

  3.每一个级别都是其更低级别的子集,并且是有序的;

  4.如果关键字 key在 级别level=i中出现,则,level<=i的链表中都会包含该关键字key;

posted on 2013-08-20 09:34  潇洒kman  阅读(203)  评论(0编辑  收藏  举报