這篇文章僅限小編個人的理解,小編不是Java方向的,只是對Java有很高的學習興趣
如果有什么不對的地方還望大佬指點
QQ交流群: 99979568
HashMap的底層是數組+鏈表,(很多人應該都知道了)
JDK1.7的是數組+鏈表
(1.7只是一個例子,以前的話也是這樣后面就以1.7為例子了)
首先是一個數組,然后數組的類型是鏈表
元素是頭插法
JDK1.8的是數組+鏈表 或者 數組+紅黑樹
首先是一個數組,然后數組的類型是鏈表
在鏈表的元素大於8的時候,會變成紅黑樹
在紅黑樹的元素小於6的時候會變成鏈表
(這里需要注意,不是元素小於6的時候一定會變成鏈表,只有resize的時候才會根據UNTREEIFY_THRESHOLD 進行轉換,同樣也不是到8的時候就變成紅黑樹 鏈表與紅黑樹的轉換詳情)
元素進行尾插
HaspMap的數組默認大小為16
數組也叫做Hash桶
(貌似聽說這個值和阿里巴巴Java開發手冊好像有點關系)
HashMap元素的下標是
HashCode(元素) & (數組的長度-1)
HashMap的擴容 Resize
擴容的話,這里有一個值叫做loadFactor(閾值),默認值為0.75;
當數組的 元素數量>數組大小(默認16)* loadFactor(默認0.75)
就會觸發擴容,擴容是二倍擴容的 (默認是16擴容后就是32)
這時原來每個元素的下標也會改變的(因為數組的長度變了)
然后就要把每個元素重新分配下標,重新加入鏈表或者紅黑樹
HashMap線程不安全
在put的時候,Resize(擴容)會造成數據的覆蓋
JDK1.7 因為是頭插法,可能會造成循環鏈表
JDK1.8 是尾插法
使用HashMap怎么才能讓他線程安全
使用ConcurrentHashMap,
JDK1.7的是分段數組,有Segment鎖(繼承於ReentrantLock)加速一小段保證並發
JDK1.8 是和HashMap一樣了,數組+鏈表(或者紅黑樹)
Synchronized(鎖)and CAS(compare and swap)
(JVM在1.6對Synchronize的優化很好)
CAS通俗易懂,比較並替換
(CAS是一種無鎖算法,CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改為B,否則什么都不做)
(無鎖化的修改值的操作,他可以大大降低鎖代理的性能消耗。這個算法的基本思想就是不斷地去比較當前內存中的變量值與你指定的 一個變量值是否相等,如果相等,則接受你指定的修改的值,否則拒絕你的操作。因為當前線程中的值已經不是最新的值,你的修改很可能會覆蓋掉其他線程修改的結果。這一點與樂觀鎖,SVN的思想是比較類似的)
使用HashTable(基本是廢棄的)
HashTable就是把HashMap套上了一個Synchronized
Collections.synchronizedMap()包裝
使用synchronized 加上,但是這個是對某個Hash桶(數組的某個值)加鎖,並不是整個map加鎖,在鎖定的時候別的線程也可以進行訪問
小編暫時就了解這個多了,有什么遺漏的還望大佬評論