ConcurrentHashMap核心知识点整理(持续更新)
Posted 泡^泡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ConcurrentHashMap核心知识点整理(持续更新)相关的知识,希望对你有一定的参考价值。
为什么ConcurrentHashMap不允许插入空值
在多线程的复杂情况下,到底是插入的null(空)值,还是本就没有才返回的null(空)值。产生的歧义不能证伪。
ConcurrentHashMap默认初始容量是多少
从下面ConcurrentHashMap类的静态变量可以看出它的初始容量为16。
ConCurrentHashmap 的key,value是否可以为null
不行 如果key或者value为null会抛出空指针异常。
ConCurrentHashmap 每次扩容是原来容量的几倍
2倍 在transfer方法里面会创建一个原数组的俩倍的node数组来存放原数据。
ConCurrentHashmap的数据结构是怎么样的
在java1.8中,它是一个数组+链表+红黑树的数据结构。
存储在ConCurrentHashmap中每个节点是什么样的,有哪些变量
它是实现Map.Entry<K,V>接口。里面存放了hash,key,value,以及next节点。它的value和next节点是用volatile进行修饰,可以保证多线程之间的可见性。
static class Node<K,V> implements Map.Entry<K,V>
final int hash;
final K key;
volatile V val;
volatile Node<K,V> next;
Node(int hash, K key, V val, Node<K,V> next)
this.hash = hash;
this.key = key;
this.val = val;
this.next = next;
ConCurrentHashmap的put过程是怎样的
整体流程跟HashMap比较类似,大致是以下几步:
如果桶数组未初始化,则初始化;
如果待插入的元素所在的桶为空,则尝试把此元素直接插入到桶的第一个位置;
如果正在扩容,则当前线程一起加入到扩容的过程中;
如果待插入的元素所在的桶不为空且不在迁移元素,则锁住这个桶(分段锁);
如果当前桶中元素以链表方式存储,则在链表中寻找该元素或者插入元素;
如果当前桶中元素以红黑树方式存储,则在红黑树中寻找该元素或者插入元素;
如果元素存在,则返回旧值;
如果元素不存在,整个Map的元素个数加1,并检查是否需要扩容;
添加元素操作中使用的锁主要有(自旋锁 + CAS + synchronized + 分段锁)。
java1.8中ConCurrentHashmap节点是尾插还是头插
尾插法
java1.8中,ConCurrentHashmap什么情况下链表才会转换成红黑树进行存储
链表长度大于8。数组长度大于64。从put源码和以下源码可以看出:并非一开始就创建红黑树结构,如果当前Node数组长度小于阈值MIN_TREEIFY_CAPACITY,默认为64,先通过扩大数组容量为原来的两倍以缓解单个链表元素过大的性能问题。
java1.8中,ConCurrentHashmap的get过程是怎样的
计算 hash 值
根据 hash 值找到数组对应位置: (n - 1) & h
根据该位置处节点性质进行相应查找
如果该位置为 null,那么直接返回 null 就可以了
如果该位置处的节点刚好就是我们需要的,返回该节点的值即可
如果该位置节点的 hash 值小于 0,说明正在扩容,或者是红黑树,后面我们再介绍 find 方法如果以上 3 条都不满足,那就是链表,进行遍历比对即可
java1.8中,ConCurrentHashmap是如何计算它的size大小的
对于size的计算,在扩容和addCount()方法就已经有处理了,可以注意一下Put函数,里面就有函数。
ConcurrentHashMap使用什么技术来保证线程安全
jdk1.7:Segment+HashEntry来进行实现的;
jdk1.8:放弃了Segment臃肿的设计,采用Node+CAS+Synchronized来保证线程安全;
ConcurrentHashMap的get方法是否要加锁,为什么
不需要,get方法采用了unsafe方法,来保证线程安全。
ConcurrentHashMap迭代器是强一致性还是弱一致性?HashMap呢
弱一致性,HashMap强一直性。
ConcurrentHashMap可以支持在迭代过程中,向map添加新元素,而HashMap则抛出了ConcurrentModificationException,因为HashMap包含一个修改计数器,当你调用他的next()方法来获取下一个元素时,迭代器将会用到这个计数器。
ConcurrentHashMap1.7和1.8的区别
jdk1.8的实现降低锁的粒度,jdk1.7锁的粒度是基于Segment的,包含多个HashEntry,而jdk1.8锁的粒度就是Node
数据结构:jdk1.7 Segment+HashEntry;jdk1.8 数组+链表+红黑树+CAS+synchronized
ConcurrentHashMap1.7介绍
整个ConcurrentHashMap是由一个一个的Segment组成,Segment代表一个分段,一个Segment里面包含一个HashEntry数组,每个HashEntry是一个链表结构,当对HashEntry数组的数据进行修改的时候,必须首先获得与它对应的Segment锁。
以上是关于ConcurrentHashMap核心知识点整理(持续更新)的主要内容,如果未能解决你的问题,请参考以下文章
Java并发集合类ConcurrentHashMap底层核心源码解析
带你整理面试中关于HashCodeHashMapConcurrnetHashMapHashTableTreeMapLinkedHashMap的相关知识点