hashmap put过程_阿里十年技术大咖,教你如何分析1.7中HashMap死循环
在多線程環(huán)境下,使用HashMap進(jìn)行put操作會(huì)引起死循環(huán),導(dǎo)致CPU利用率接近100%,HashMap在并發(fā)執(zhí)行put操作時(shí)會(huì)引起死循環(huán),是因?yàn)槎嗑€程會(huì)導(dǎo)致HashMap的Entry鏈表
形成環(huán)形數(shù)據(jù)結(jié)構(gòu),一旦形成環(huán)形數(shù)據(jù)結(jié)構(gòu),Entry的next節(jié)點(diǎn)永遠(yuǎn)不為空,就會(huì)產(chǎn)生死循環(huán)獲取Entry。那么這個(gè)死循環(huán)是如何生成的呢?我們來(lái)仔細(xì)分析下。
HashMap擴(kuò)容流程
原理
引發(fā)死循環(huán),是在HashMap的擴(kuò)容操作中,正常的擴(kuò)容操作是這個(gè)流程。HashMap的擴(kuò)容在put操作中會(huì)觸發(fā)擴(kuò)容,主要是三個(gè)方法:
綜合來(lái)說(shuō),HashMap一次擴(kuò)容的過(guò)程:
1、取當(dāng)前table的2倍作為新table的大小
2、根據(jù)算出的新table的大小new出一個(gè)新的Entry數(shù)組來(lái),名為newTable
3、輪詢?cè)璽able的每一個(gè)位置,將每個(gè)位置上連接的Entry,算出在新table上的位置,并以鏈表形式連接
4、原table上的所有Entry全部輪詢完畢之后,意味著原table上面的所有Entry已經(jīng)移到了新的table上,HashMap中的table指向newTable
實(shí)例
現(xiàn)在hashmap中有三個(gè)元素,Hash表的size=2, 所以key = 3, 7, 5,在mod 2以后都沖突在table[1]這里了。
按照方法中的代碼
對(duì)table[1]中的鏈表來(lái)說(shuō),進(jìn)入while循環(huán),此時(shí)e=key(3),那么next=key(7),經(jīng)過(guò)計(jì)算重新定位e=key(3)在新表中的位置,并把e=key(3)掛在newTable[3]的位置
這樣循環(huán)下去,將table[1]中的鏈表循環(huán)完成后,于是HashMap就完成了擴(kuò)容
并發(fā)下的擴(kuò)容
上面都是單線程下的擴(kuò)容,當(dāng)多線程進(jìn)行擴(kuò)容時(shí),會(huì)是什么樣子呢?
初始的HashMap還是:
我們現(xiàn)在假設(shè)有兩個(gè)線程并發(fā)操作,都進(jìn)入了擴(kuò)容操作, 我們以顏色進(jìn)行區(qū)分兩個(gè)線程。
回顧我們的擴(kuò)容代碼,我們假設(shè),線程1執(zhí)行到Entry next = e.next;時(shí)被操作系統(tǒng)調(diào)度掛起了,而線程2執(zhí)行完成了擴(kuò)容操作
于是,在線程1,2看來(lái),就應(yīng)該是這個(gè)樣子
接下來(lái),線程1被調(diào)度回來(lái)執(zhí)行:
循環(huán)列表產(chǎn)生后,一旦線程1調(diào)用get(11,15之類的元素)時(shí),就會(huì)進(jìn)入一個(gè)死循環(huán)的情況,將CPU的消耗到100%。
總結(jié)
HashMap之所以在并發(fā)下的擴(kuò)容造成死循環(huán),是因?yàn)?#xff0c;多個(gè)線程并發(fā)進(jìn)行時(shí),因?yàn)橐粋€(gè)線程先期完成了擴(kuò)容,將原的鏈表重新散列到自己的表中,并且鏈表變成了倒序,后一個(gè)線程再擴(kuò)容時(shí),又進(jìn)行自己的散列,再次將倒序鏈表變?yōu)檎蜴湵?。于是形成了一個(gè)環(huán)形鏈表,當(dāng)表中不存在的元素時(shí),造成死循環(huán)。
雖然在JDK1.8中,Java的開(kāi)發(fā)小組修正了這個(gè)問(wèn)題,但是HashMap始終存在著其他的線程安全問(wèn)題。所以在并發(fā)情況下,我們應(yīng)該使用HastTable或者ConcurrentHashMap來(lái)代替HashMap。
最后在這分享一下一直以來(lái)整理的Java學(xué)習(xí)資料,大家關(guān)注后私聊我,我會(huì)免費(fèi)分享給大家的!
總結(jié)
以上是生活随笔為你收集整理的hashmap put过程_阿里十年技术大咖,教你如何分析1.7中HashMap死循环的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 交强险过期半年,再交怎么算 交强险过期半
- 下一篇: 多多买菜怎么解绑银行卡 怎么解绑多多买菜