Java8 ConcurrentSkipListMap与ConcurrentSkipListSet (一) 源码解析

     目录

一、ConcurrentSkipListSet

二、ConcurrentSkipListMap

1、定义

2、Node / Index / HeadIndex

3、SkipList 跳跃表

4、构造方法

5、put / putIfAbsent 

6、remove / replace / replaceAll / clear

7、get / getOrDefault


      ConcurrentSkipListSet是基于ConcurrentSkipListMap实现的线程安全的NavigableSet接口实现类,与之对应的线程不安全的实现类就是基于TreeMap实现的TreeSet;ConcurrentNavigableMap是基于SkipList跳跃表实现的线程安全的NavigableMap实现类,后者对应的线程不安全的实现类就是基于红黑树实现的TreeMap。本篇博客就详细探讨这两类的实现细节。

一、ConcurrentSkipListSet

      ConcurrentSkipListSet的类继承关系如下:

       

     其实现的核心接口NavigableSet的另一个典型实现类就是TreeSet,跟TreeSet基于TreeMap实现一样, ConcurrentSkipListSet的实现基于ConcurrentSkipListMap的,添加和删除元素,元素遍历等都是基于ConcurrentSkipListMap方法的,value固定为Boolean.TRUE,其常用方法实现如下:

public ConcurrentSkipListSet() {
        m = new ConcurrentSkipListMap<E,Object>();
    }

public ConcurrentSkipListSet(Comparator<? super E> comparator) {
        m = new ConcurrentSkipListMap<E,Object>(comparator);
    }


public boolean add(E e) {
        return m.putIfAbsent(e, Boolean.TRUE) == null;
    }

public boolean remove(Object o) {
        return m.remove(o, Boolean.TRUE);
    }

public Iterator<E> iterator() {
        return m.navigableKeySet().iterator();
    }

public Iterator<E> descendingIterator() {
        return m.descendingKeySet().iterator();
    }

二、ConcurrentSkipListMap

1、定义

     ConcurrentSkipListMap的类继承关系如下:

     

     从上图可知,ConcurrentNavigableMap继承自ConcurrentMap和NavigableMap,后者的典型实现类就是TreeMap,纯粹是基于红黑树实现的,可以参考《java8 TreeMap接口实现源码解析》。ConcurrentNavigableMap没有添加新的方法,只是改写了父类接口的方法定义,如下:

这些方法的用途可以参考API,会挑选其中典型的方法研究其实现细节。该类包含的属性如下:

    //头索引节点
    private transient volatile HeadIndex<K,V> head;

    //比较大小的比较器
    final Comparator<? super K> comparator;
  
    //key视图,下面这些视图都是在请求相关方法时才会创建
    private transient KeySet<K> keySet;
    //键值对视图
    private transient EntrySet<K,V> entrySet;
    //value视图
    private transient Values<V> values;
    //倒序遍历的视图
    private transient ConcurrentNavigableMap<K,V> descendingMap;

 包含的静态常量如下:

//初始化head属性时使用,表示一个空节点
private static final Object BASE_HEADER = new Object();

private static final int EQ = 1;
private static final int LT = 2;
private static final int GT = 0; // Actually checked as !LT

包含的静态属性通过static代码块初始化,如下:

2、Node / Index / HeadIndex

     这三个都是内部类,其中Node表示一个键值对,其定义如下:

static final class Node<K,V> {
        //键值对的key和value
        final K key;
        volatile Object value;
        //链表中的下一个节点
        volatile Node<K,V> next;

        Node(K key, Object value, Node<K,V> next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        Node(Node<K,V> next) {
            this.key = null;
            this.value = this;
            this.next = next;
        }
        
        //cas修改value
        boolean casValue(Object cmp, Object val) {
            return UNSAFE.compareAndSwapObject(this, valueOffset, cmp, val);
        }
        
        //cas修改next
        boolean casNext(Node<K,V> cmp, Node<K,V> val) {
            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
        }

        boolean isMarker() {
            return value == this;
        }

        boolean isBaseHeader() {
            return value == BASE_HEADER;
        }
        
        //插入一个value指向自己的节点,next为f的节点
        //删除某个节点时会将其value置为null,然后调用此方法在该节点后插入一个marker,将该节点从next链表中移除
        //marker在这里是打一个标识同时保存下一个节点的引用,保证将其从next链表中移除失败,即cas修改前一个节点的next属性失败的情形下该节点可以被正常移除
        boolean appendMarker(Node<K,V> f) {
            return casNext(f, new Node<K,V>(f));
        }
        
        //在查询或者修改节点时,发现某个节点的value已经是null了,会调用此方法
        //b是前一个节点,f是next节点
        void helpDelete(Node<K,V> b, Node<K,V> f) {
            if (f == next && this == b.next) {
                //再次检查链表关系
                if (f == null || f.value != f) 
                    //该节点未插入marker节点,此处重新插入,下次调用时进入else分支
                    casNext(f, new Node<K,V>(f));
                else
                    //f是一个marker节点
                    //将this和f都从链表中移除
                    b.casNext(this, f.next);
            }
        }

       
        V getValidValue() {
            Object v = value;
            if (v == t
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值