zoukankan      html  css  js  c++  java
  • Java | JDK8下的ConcurrentHashMap#putValue

    
    
     1  /**
     2       key:键值
     3       value:值
     4       onlyIfAbsent:true:如果key存在的情况下,不更新值;Flase:如果key存在的情况下,替换old value
     5   **/
     6   final V putVal(K key, V value, boolean onlyIfAbsent) {
     7           //不允许key或value为空
     8         if (key == null || value == null) throw new NullPointerException();
     9         //在key的hascode值上重新计算key的hash值
    10         //【(key.hashCode() ^ (key.hashCode() >>> 16)) & 0x7fffffff;】
    11         int hash = spread(key.hashCode());
    12         int binCount = 0;
    13         //CAS锁
    14         for (Node<K,V>[] tab = table;;) {
    15             Node<K,V> f; int n, i, fh;
    16             /**
    17                 初始化
    18                 根据hash确认key的Node位置,当node为空时则CAS尝试写入,写入成功流程结束,否则进行下一次尝试
    19             **/         
    20             if (tab == null || (n = tab.length) == 0)
    21                 tab = initTable();
    22             else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
    23                 if (casTabAt(tab, i, null,
    24                              new Node<K,V>(hash, key, value, null)))
    25                     break;                   // no lock when adding to empty bin
    26             }
    27             /**
    28                 static final int MOVED = -1;
    29                 如果当前位置的 hashcode == MOVED == -1, map 正在扩容,其他线程帮助扩容,也就是多线程扩容。
    30             **/
    31             else if ((fh = f.hash) == MOVED)
    32                 tab = helpTransfer(tab, f);
    33             else {
    34             /**
    35                 利用 synchronized 锁写入数据
    36                 fh〉0 说明这个节点是一个链表的节点不是树的节点。
    37                 如果是红黑树,照树的方式插入值        
    38             **/
    39                 V oldVal = null;
    40                 synchronized (f) {
    41                     if (tabAt(tab, i) == f) {
    42                         if (fh >= 0) {
    43                             binCount = 1;
    44                             //遍历链表所有结点,如果找到相同key就更新旧值,否则添加至链表尾
    45                             for (Node<K,V> e = f;; ++binCount) {
    46                                 K ek;
    47                                 if (e.hash == hash &&
    48                                     ((ek = e.key) == key ||
    49                                      (ek != null && key.equals(ek)))) {
    50                                     oldVal = e.val;
    51                                     if (!onlyIfAbsent)
    52                                         e.val = value;
    53                                     break;
    54                                 }
    55                                 Node<K,V> pred = e;
    56                                 if ((e = e.next) == null) {
    57                                     pred.next = new Node<K,V>(hash, key,
    58                                                               value, null);
    59                                     break;
    60                                 }
    61                             }
    62                         }
    63                         else if (f instanceof TreeBin) {
    64                             Node<K,V> p;
    65                             binCount = 2;
    66                             if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
    67                                                            value)) != null) {
    68                                 oldVal = p.val;
    69                                 if (!onlyIfAbsent)
    70                                     p.val = value;
    71                             }
    72                         }
    73                     }
    74                 }
    75                 /**
    76                     当链表长度大于8时,将链表转换为红黑树
    77                 **/
    78                 if (binCount != 0) {
    79                     if (binCount >= TREEIFY_THRESHOLD)
    80                         treeifyBin(tab, i);
    81                     if (oldVal != null)
    82                         return oldVal;
    83                     break;
    84                 }
    85             }
    86         }
    87         //如果是新增元素,将当前ConcurrentHashMap的元素数量+1
    88         addCount(1L, binCount);
    89         return null;
    90     }
  • 相关阅读:
    php openssl 加密解密
    PHP中进制之间的互相转换
    零基础学习FFMPEG
    git 强制更新本地和强制提交覆盖
    mysql 不常用备忘
    mysql <=> null 问题
    GD库imagettftext中文乱码的问题
    flex布局设置width无效
    下拉菜单css
    swagger:API在线文档自动生成框架
  • 原文地址:https://www.cnblogs.com/jj81/p/11479222.html
Copyright © 2011-2022 走看看