文章目錄
- 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 bins
initialCapacity = concurrencyLevel; // as estimated threads
long 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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/265857.html
標籤:其他
上一篇:基于JWT的Token認證
下一篇:【進擊面試_03】Java 并發
