【Java自顶向下】ConcurrentHashMap面试题(2021最新版)
文章目錄
- 1 ConcurrentHashMap默認初始容量是多少?
- 2 ConCurrentHashmap 的key,value是否可以為null。
- 3 ConCurrentHashmap 每次擴容是原來容量的幾倍
- 4 ConCurrentHashmap的數據結構是怎么樣的?(后面會具體分析它的put方法)
- 5 存儲在ConCurrentHashmap中每個節點是什么樣的,有哪些變量
- 6 ConCurrentHashmap的put過程是怎樣的?
- 7 java1.8中ConCurrentHashmap節點是尾插還是頭插?
- 8 java1.8中,ConCurrentHashmap什么情況下鏈表才會轉換成紅黑樹進行存儲?
- 9 java1.8中,ConCurrentHashmap的get過程是怎樣的?
- 10 java1.8中,ConCurrentHashmap是如何計算它的size大小的?
- 11 ConcurrentHashMap有哪些構造函數?
- 12 ConcurrentHashMap使用什么技術來保證線程安全?
- 13 ConcurrentHashMap的get方法是否要加鎖,為什么?
- 14 ConcurrentHashMap迭代器是強一致性還是弱一致性?HashMap呢?
- 15 ConcurrentHashMap1.7和1.8的區別
1 ConcurrentHashMap默認初始容量是多少?
從下面ConcurrentHashMap類的靜態變量可以看出它的初始容量為16
2 ConCurrentHashmap 的key,value是否可以為null。
不行 如果key或者value為null會拋出空指針異常
3 ConCurrentHashmap 每次擴容是原來容量的幾倍
2倍 在transfer方法里面會創建一個原數組的倆倍的node數組來存放原數據。
4 ConCurrentHashmap的數據結構是怎么樣的?(后面會具體分析它的put方法)
在java1.8中,它是一個數組+鏈表+紅黑樹的數據結構。
5 存儲在ConCurrentHashmap中每個節點是什么樣的,有哪些變量
它是實現Map.Entry<K,V>接口。里面存放了hash,key,value,以及next節點。它的value和next節點是用volatile進行修飾,可以保證多線程之間的可見性。
6 ConCurrentHashmap的put過程是怎樣的?
整體流程跟HashMap比較類似,大致是以下幾步:
(1)如果桶數組未初始化,則初始化;
(2)如果待插入的元素所在的桶為空,則嘗試把此元素直接插入到桶的第一個位置;
(3)如果正在擴容,則當前線程一起加入到擴容的過程中;
(4)如果待插入的元素所在的桶不為空且不在遷移元素,則鎖住這個桶(分段鎖);
(5)如果當前桶中元素以鏈表方式存儲,則在鏈表中尋找該元素或者插入元素;
(6)如果當前桶中元素以紅黑樹方式存儲,則在紅黑樹中尋找該元素或者插入元素;
(7)如果元素存在,則返回舊值;
(8)如果元素不存在,整個Map的元素個數加1,并檢查是否需要擴容;
添加元素操作中使用的鎖主要有(自旋鎖 + CAS + synchronized + 分段鎖)。
7 java1.8中ConCurrentHashmap節點是尾插還是頭插?
尾插法,見上述put方法。
8 java1.8中,ConCurrentHashmap什么情況下鏈表才會轉換成紅黑樹進行存儲?
鏈表長度大于8。數組長度大于64。從put源碼和以下源碼可以看出:并非一開始就創建紅黑樹結構,如果當前Node數組長度小于閾值MIN_TREEIFY_CAPACITY,默認為64,先通過擴大數組容量為原來的兩倍以緩解單個鏈表元素過大的性能問題。
9 java1.8中,ConCurrentHashmap的get過程是怎樣的?
1、計算 hash 值
2、根據 hash 值找到數組對應位置: (n - 1) & h
3、根據該位置處結點性質進行相應查找
如果該位置為 null,那么直接返回 null 就可以了
如果該位置處的節點剛好就是我們需要的,返回該節點的值即可
如果該位置節點的 hash 值小于 0,說明正在擴容,或者是紅黑樹,后面我們再介紹 find 方法如果以上 3 條都不滿足,那就是鏈表,進行遍歷比對即可
10 java1.8中,ConCurrentHashmap是如何計算它的size大小的?
對于size的計算,在擴容和addCount()方法就已經有處理了,可以注意一下Put函數,里面就有addCount()函數。
11 ConcurrentHashMap有哪些構造函數?
一共有五個,作用及代碼如下:
//無參構造函數public ConcurrentHashMap() {}//可傳初始容器大小的構造函數public ConcurrentHashMap(int initialCapacity) {if (initialCapacity < 0)throw new IllegalArgumentException();int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?MAXIMUM_CAPACITY :tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));this.sizeCtl = cap;}//可傳入map的構造函數public ConcurrentHashMap(Map<? extends K, ? extends V> m) {this.sizeCtl = DEFAULT_CAPACITY;putAll(m);}//可設置閾值和初始容量public ConcurrentHashMap(int initialCapacity, float loadFactor) {this(initialCapacity, loadFactor, 1);}//可設置初始容量和閾值和并發級別public ConcurrentHashMap(int initialCapacity,float loadFactor, int concurrencyLevel) {if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)throw new IllegalArgumentException();if (initialCapacity < concurrencyLevel) // Use at least as many binsinitialCapacity = concurrencyLevel; // as estimated threadslong size = (long)(1.0 + (long)initialCapacity / loadFactor);int cap = (size >= (long)MAXIMUM_CAPACITY) ?MAXIMUM_CAPACITY : tableSizeFor((int)size);this.sizeCtl = cap;}12 ConcurrentHashMap使用什么技術來保證線程安全?
jdk1.7:Segment+HashEntry來進行實現的;
jdk1.8:放棄了Segment臃腫的設計,采用Node+CAS+Synchronized來保證線程安全;
13 ConcurrentHashMap的get方法是否要加鎖,為什么?
不需要,get方法采用了unsafe方法,來保證線程安全。
14 ConcurrentHashMap迭代器是強一致性還是弱一致性?HashMap呢?
弱一致性,HashMap強一直性。
ConcurrentHashMap可以支持在迭代過程中,向map添加新元素,而HashMap則拋出了ConcurrentModificationException,因為HashMap包含一個修改計數器,當你調用他的next()方法來獲取下一個元素時,迭代器將會用到這個計數器。
15 ConcurrentHashMap1.7和1.8的區別
jdk1.8的實現降低鎖的粒度,jdk1.7鎖的粒度是基于Segment的,包含多個HashEntry,而jdk1.8鎖的粒度就是Node
數據結構:jdk1.7 Segment+HashEntry;jdk1.8 數組+鏈表+紅黑樹+CAS+synchronized
總結
以上是生活随笔為你收集整理的【Java自顶向下】ConcurrentHashMap面试题(2021最新版)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java自顶向下】面试官:HashMa
- 下一篇: 【Java自顶向下】试手小公司,面试官问