一、前言
最近在做项目的同时也在修复之前项目的一些Bug,所以忙得没有时间看源代码,今天都完成得差不多了,所以又开始源码分析之路,也着笔记录下ConcurrentSkipListMap的源码的分析过程。
二、ConcurrentSkipListMap数据结构
抓住了数据结构,对于理解整个ConcurrentSkipListMap有很重要的作用,其实,通过源码可知其数据结构如下。
说明:可以看到ConcurrentSkipListMap的数据结构使用的是跳表,每一个HeadIndex、Index结点都会包含一个对Node的引用,同一垂直方向上的Index、HeadIndex结点都包含了最底层的Node结点的引用。并且层级越高,该层级的结点(HeadIndex和Index)数越少。Node结点之间使用单链表结构。
三、ConcurrentSkipListMap源码分析
3.1 类的继承关系
public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> implements ConcurrentNavigableMap<K,V>, Cloneable, Serializable {}
说明:ConcurrentSkipListMap继承了AbstractMap抽象类,实现了ConcurrentNavigableMap接口,该接口定义了获取某一部分集合的操作。实现了Cloneable接口,表示允许克隆。实现了Serializable接口,表示可被序列化。
3.2 类的内部类
ConcurrentSkipListMap包含了很多内部类,内部类的框架图如下:
说明:其中,最为重要的类包括Index、HeadIndex、Node三个类。下面对这三个类进行逐一讲解,其他的类,读者有兴趣可以自行分析。
① Index类
1. 类的属性
static class Index<K,V> { final Node<K,V> node; final Index<K,V> down; volatile Index<K,V> right; // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long rightOffset; static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class<?> k = Index.class; rightOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("right")); } catch (Exception e) { throw new Error(e); } } }
说明:可以看到,Index结点包括一个Node结点的引用,都是包含down域和right域,即对应数据结构中的Index结点。并且借助了反射来原子性的修改right域。
2. 类的构造函数
/** * Creates index node with given values. */ Index(Node<K,V> node, Index<K,V> down, Index<K,V> right) { this.node = node; this.down = down; this.right = right; }