Java | JDK8下的ConcurrentHashMap#putValue

Posted jj81

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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     

 

以上是关于Java | JDK8下的ConcurrentHashMap#putValue的主要内容,如果未能解决你的问题,请参考以下文章

Java ArrayList底层实现原理源码详细分析Jdk8

JDK8下的HashMap有什么特别之处?

Linux安装jdk8及环境变量配置

Linux安装jdk8及环境变量配置

jdk8与jdk9的共存

java开发-问题清单