ConcurrentHashmap进行添加元素操作的源码分析以及注释。

ConcurrentHashmap进行添加元素操作的源码分析以及注释。

  1. 判断需要插入的key/vlaue是否为null。
  2. 计算hash。
  3. 遍历存放数据的Node数组,并判断数组是否为空,为空则进行初始化。
  4. 根据算出数组下标并判断该点是否为空,若为空,cas尝试添加操作。
  5. 判断数组是否正在进行扩容,正在扩容协助其进行扩容。
  6. 对该node节点进行加锁操作,并进行元素插入。
  7. 判断链表长度,并尝试是否需要进行红黑树转化。
  8. 维护数组长度,并判断是否需要进行扩容操作。
/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
    //如果key值或者value为空,则报空指针。concurrenthashmap不允许key、value为空
    if (key == null || value == null) throw new NullPointerException();
    //计算hash值
    int hash = spread(key.hashCode());
    int binCount = 0;
    //遍历存放数据的Node数组
    for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
        //如果数组为空,则进行初始化操作。
        if (tab == null || (n = tab.length) == 0)
            tab = initTable();
        //使用数组大小n-1和hash值做按位与操作得到数组下标并获取该位置数组元素赋值给变量f
        //如果f为空,使用cas进行尝试插入操作,成功跳出循环。
        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            if (casTabAt(tab, i, null,
                         new Node<K,V>(hash, key, value, null)))
                break;                   // no lock when adding to empty bin
        }
        //如果数组正在扩容,则协助扩容。
        else if ((fh = f.hash) == MOVED)
            tab = helpTransfer(tab, f);
        else {
            V oldVal = null;
            //将当前节点f进行加锁操作,但是不影响其他桶的操作。
            synchronized (f) {
                //校验当前节点位置是否改变。
                if (tabAt(tab, i) == f) {
                    if (fh >= 0) {
                        binCount = 1;
                        //循环遍历链表,
                        for (Node<K,V> e = f;; ++binCount) {
                            K ek;
                            //比对key值的equals是否相等
                            if (e.hash == hash &&
                                ((ek = e.key) == key ||
                                 (ek != null && key.equals(ek)))) {
                                //相等就替换该节点的value值
                                oldVal = e.val;
                                if (!onlyIfAbsent)
                                    e.val = value;
                                break;
                            }
                            Node<K,V> pred = e;
                            //如果不存在该key,找到链尾,插入数据。
                            if ((e = e.next) == null) {
                                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) {
                //如果链表长度大于8
                if (binCount >= TREEIFY_THRESHOLD)
                    //进入treeifyBin方法,尝试转化为红黑树(如果数组的长度也大于或等于MIN_TREEIFY_CAPACITY=64)。
                    treeifyBin(tab, i);
                if (oldVal != null)
                    return oldVal;
                break;
            }
        }
    }
    //维护数组长度,并判断是否需要进行扩容。
    addCount(1L, binCount);
    return null;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值