ConcurrentHashMap的存储流程如下:
-
根据key的hash值得到数组索引ConcurrentHashMap底层是由一个数组构成的,数组的每个元素是一个链表。第一个步骤是根据key的hash值通过hash算法得到在这个数组中的索引。
-
CAS插入数组元素使用CAS(比较和交换)操作尝试将这个key-value插入到得到的数组索引位置。如果这个位置的元素为空,或者元素的key与要插入的key一致,那么插入成功。
-
如果CAS失败,遍历链表如果CAS插入失败,说明这个位置的元素的key与要插入的key不一致,这时会对这个位置的链表进行遍历,依次比较各个节点的key是否与要插入的key一致。如果不一致就进行下一个,一致就覆盖这个节点的值。
-
如果遍历完毕仍失败,则使用CAS尾插法插入如果遍历完这个位置的链表仍没有找到相同key的节点,这时会使用CAS尾插法将这个新节点插入到链表的尾部。也就是说会使用CAS操作尝试将新节点插入到链表的最后一个节点的next字段。如果CAS成功则插入成功,如果CAS失败则有并发插入,重新进行步骤3。
-
如果超过链表长度阈值,则将链表转化为红黑树如果一个位置的链表长度超过8,ConcurrentHashMap会将这个链表转化为红黑树,以提高查询效率。前面几步同样适用于红黑树。
简而言之,ConcurrentHashMap的插入流程就是:
1.计算key的hash值得到数组索引
2.尝试使用CAS直接插入这个位置
3.如果CAS失败,遍历链表查找是否已存在这个key的节点
4.如果不存在,使用CAS尾插法插入到链表尾部
5.如果链表长度超过8,转化为红黑树这是一个相当高效的流程,既解决了并发插入的问题,也控制了链表长度,避免性能损耗。ConcurrentHashMap的高性能与此密不可分。理解其存储流程,有助于我们在使用时获得更好的性能。