ConcurrentHashMap1.8源码解析

1.属性介绍

常量

// 最大容量
private static final int MAXIMUM_CAPACITY = 1 << 30;
// 默认容量
private static final int DEFAULT_CAPACITY = 16;
// 默认加载因子
private static final float LOAD_FACTOR = 0.75f;
// 链表长度树化阈值
static final int TREEIFY_THRESHOLD = 8;
// 树形转链表阈值
static final int UNTREEIFY_THRESHOLD = 6;
// 最小树化容量
static final int MIN_TREEIFY_CAPACITY = 64;

实例属性

// 存储数据的table
transient volatile Node<K,V>[] table;
// 表初始化和调整大小控制。如果为负数,则表正在初始化或调整大小:-1 表示初始化,否则 -(1 + 活动调整大小线程的数量)。否则,当 table 为 null 时,保存要在创建时使用的初始表大小,或者默认为 0。初始化后,保存下一个元素计数值,根据该值调整表的大小
private transient volatile int sizeCtl;

2.构造方法

无参构造

public ConcurrentHashMap() {
}

有参构造

public ConcurrentHashMap(int initialCapacity) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException();
    // 
    int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
               MAXIMUM_CAPACITY :
               tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
    this.sizeCtl = cap;
}

public ConcurrentHashMap(int initialCapacity, float loadFactor) {
    this(initialCapacity, loadFactor, 1);
}

public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel) {
    if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
        throw new IllegalArgumentException();
    // 当前初始化容量小于初始化并发级别,则直接将初始化容量赋值为并发级别
    if (initialCapacity < concurrencyLevel)  
        initialCapacity = concurrencyLevel;  
    // 根据初始化容量和初始化加载因子来计算当前容量
    long size = (long)(1.0 + (long)initialCapacity / loadFactor);
    // 取比size大的最小2次幂
    int cap = (size >= (long)MAXIMUM_CAPACITY) ?
        MAXIMUM_CAPACITY : tableSizeFor((int)size);
    // 设置为当前初始化的容量
    this.sizeCtl = cap;
}

2.1 tableSizeFor()

private static final int tableSizeFor(int c) {
    // 通过位运算计算得到比c大的最小2次幂
    int n = c - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

3.put()

public V put(K key, V value) {
    return putVal(key, value, false);
}

final V putVal(K key, V value, boolean onlyIfAbsent) {
    // put的ket、value不能为null
    if (key == null || value == null) throw new NullPointerException();
    // 扰动处理,减少hash冲突概率
    int hash = spread(key.hashCode());
    int binCount = 0;
    for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
        if (tab == null || (n = tab.length) == 0)
            // 详见3.1 initTable()
            tab = initTable();
        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { // 当前下标i对应元素值为null
            if (casTabAt(tab, i, null,
                         new Node<K,V>(hash, key, value, null)))
                break;                   // cas,新增节点存储到对应tab[i]中
        }
        else if ((fh = f.hash) == MOVED)
            tab = helpTransfer(tab, f);
        else {
            V oldVal = null;
            synchronized (f) { // tab[i]头节点加锁
                if (tabAt(tab, i) == f) { // 判断tab[i]头节点是否改变
                    if (fh >= 0) { // f.hash值大于等于0代表当前节点是可操作的,树根节点的hash值是-2
                        binCount = 1;
                        for (Node<K,V> e = f;; ++binCount) { // 遍历f节点
                            K ek;
                            if (e.hash == hash &&
                                ((ek = e.key) == key ||
                                 (ek != null && key.equals(ek)))) { // 匹配hash、key值,若相等直接覆盖原value,并返回原value
                                oldVal = e.val;
                                if (!onlyIfAbsent)
                                    e.val = value;
                                break;
                            }
                            Node<K,V> pred = e;
                            if ((e = e.next) == null) { // 遍历完f节点,仍没有匹配key、hash值则创建新节点(尾插法)
                                pred.next = new Node<K,V>(hash, key,
                                                          value, null);
                                break;
                            }
                        }
                    }
                    else if (f instanceof TreeBin) { // 当前节点为树节点
                        Node<K,V> p;
                        binCount = 2;
                        if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
                                                       value)) != null) {
                            oldVal = p.val;
                            if (!onlyIfAbsent)
                                p.val = value;
                        }
                    }
                }
            }
            if (binCount != 0) {
                // 判断当前链表长度是否大于树化阈值
                if (binCount >= TREEIFY_THRESHOLD)
                    treeifyBin(tab, i);
                if (oldVal != null)
                    return oldVal;
                break;
            }
        }
    }
    addCount(1L, binCount); // 计数
    return null;
}

3.1 initTable()

初始化table

private final Node<K,V>[] initTable() {
    Node<K,V>[] tab; int sc;
    while ((tab = table) == null || tab.length == 0) { // 若当前table未初始化,进入循环
        if ((sc = sizeCtl) < 0) // sizeCtl<0 代表在初始化或调整大小
            Thread.yield(); // 让出cpu调度时间
        else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { // CAS 将sizeCtl修改为-1,表示当前table正在初始化
            try {
                if ((tab = table) == null || tab.length == 0) { // 双重锁检查
                    int n = (sc > 0) ? sc : DEFAULT_CAPACITY; // sc大于0表示,初始化了容量直接使用该容量,反之则使用默认容量16
                    @SuppressWarnings("unchecked")
                    Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
                    table = tab = nt; // 初始化table
                    sc = n - (n >>> 2); // sc保存当前扩容阈值,即为0.75x当前容量
                }
            } finally {
                sizeCtl = sc;
            }
            break;
        }
    }
    return tab;
}

4.get()

public V get(Object key) {
    Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
    int h = spread(key.hashCode()); //扰动函数计算hash值
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (e = tabAt(tab, (n - 1) & h)) != null) { // 判断table是否相等,tab[i]是否为空
        if ((eh = e.hash) == h) {
            if ((ek = e.key) == key || (ek != null && key.equals(ek)))
                return e.val;
        }
        else if (eh < 0) // 当前在初始化或调整大小
            return (p = e.find(h, key)) != null ? p.val : null;
        while ((e = e.next) != null) {
            if (e.hash == h &&
                ((ek = e.key) == key || (ek != null && key.equals(ek))))
                return e.val;
        }
    }
    return null;
}

Node<K,V> find(int h, Object k) {
    Node<K,V> e = this;
    // 遍历e节点比较hash、key
    if (k != null) {
        do {
            K ek;
            if (e.hash == h &&
                ((ek = e.key) == k || (ek != null && k.equals(ek))))
                return e;
        } while ((e = e.next) != null);
    }
    return null;
}

版权声明:本文为qq_40790991原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。