ConcurrentHashmAP

final V putVal(K key, V value, boolean onlyIfAbsent) {

if (key ==null || value ==null)throw new NullPointerException();

    //先计算出hash 值,然后根据hash 值来计算数组下标

    int hash =spread(key.hashCode());

    //当前链表上有多少元素

    int binCount =0;

    //死循环 何时插入成功 何时跳出

    for (Node[] tab =table; ; ) {

// table i 位置的节点(当前数组的头节点)

        Node f;

        int n, i, fh;

        //如果数组为空的时候,先进行数组的初始化

        if (tab ==null || (n = tab.length) ==0) {

tab = initTable();

            //根据hash值计算出在table里面的位置

//tabAt(tab, i = (n - 1) & hash)) 通过hash 值来获取数组的元素。

        }else if ((f =tabAt(tab, i = (n -1) & hash)) ==null) {

//通过cas 向第i个位置设置值,cas  false 重新走外面的循环

            if (casTabAt(tab, i, null, new Node(hash, key, value, null))) {

// no lock when adding to empty bin

                break;

            }

}else if ((fh = f.hash) ==MOVED) {

//static final int MOVED = -1;

//如果当前的concurrenthashmap 正在进行扩容,帮助hashmap 进行扩容。

            tab = helpTransfer(tab, f);

        }else {

V oldVal =null;

            //当前插入的元素是插入到红黑树,还是插入到链表中。

//对槽的位置进行加锁。(链表的第一个节点进行加锁)

            synchronized (f) {

//判断当前链表的头节点是不是还等于f.继续进行循环,获取新的f

                if (tabAt(tab, i) == f) {

//fh 证明没有发生过移动。当节点的hash 值是 大于0的时候证明是链表。

                    if (fh >=0) {

//是链表上面的节点。

                        binCount =1;

                        //这个地方对链表进行循环。

                        for (Node e = f; ; ++binCount) {

K ek;

                            //如果hash值和key值相同  则修改对应结点的value值

                            if (e.hash == hash && ((ek = e.key) == key || (ek !=null && key.equals(ek)))) {

oldVal = e.val;

                                if (!onlyIfAbsent) {

e.val = value;

                                }

//退出循环

                                break;

                            }

Node pred = e;

                            //如果遍历到了最后一个结点,那么就证明新的节点需要插入 就把它插入在链表尾部(尾插入)

                            if ((e = e.next) ==null) {

pred.next =new Node(hash, key, value, null);

break;

                            }

}

}else if (finstanceof TreeBin) {

//节点类型是TreeBin

//如果这个节点是树节点,就按照树的方式插入值

                        Node p;

                        binCount =2;

                        if ((p = ((TreeBin) f).putTreeVal(hash, key, value)) !=null) {

oldVal = p.val;

                            if (!onlyIfAbsent) {

p.val = value;

                            }

}

}

}

}

if (binCount !=0) {

//如果链表长度已经达到临界值8 就需要把链表转换为树结构

                if (binCount >=TREEIFY_THRESHOLD) {

//对链表进行树化

                    treeifyBin(tab, i);

                }

if (oldVal !=null)

return oldVal;

break;

            }

}

}

//扩容条件的判断

    addCount(1L, binCount);

return null;

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。