hashMap擴(kuò)容時(shí)應(yīng)該注意這些死循環(huán)問(wèn)題
hashMap死循環(huán)
1.原因: jdk1.7時(shí)使用頭插入法 ,1.8之后改成了尾插入法解決了這個(gè)問(wèn)題
HashMap死循環(huán)問(wèn)題圖解
在HashMap的數(shù)組真實(shí)長(zhǎng)度達(dá)到閾值后,會(huì)調(diào)用擴(kuò)容方法:
void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable, initHashSeedAsNeeded(newCapacity)); table = newTable; threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1); }
這里可以看到如果有兩個(gè)線程A和B,那么在調(diào)用transfer方法之前會(huì)在各自的線程中創(chuàng)建新的數(shù)組,然后進(jìn)入到transfer方法中將節(jié)點(diǎn)轉(zhuǎn)移,再看transfer方法:
void transfer(Entry[] newTable, boolean rehash) { int newCapacity = newTable.length; for (Entry<K,V> e : table) { while(null != e) { Entry<K,V> next = e.next; ------(1) if (rehash) { e.hash = null == e.key ? 0 : hash(e.key); } int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } } }
我在上面的程序中標(biāo)記了一個(gè)(1),待會(huì)會(huì)用到,首先假設(shè)HashMap中的結(jié)構(gòu)是這樣的:
那么線程A如果執(zhí)行到(1)的位置,那么e為節(jié)點(diǎn)5,next為節(jié)點(diǎn)6,這個(gè)時(shí)候線程B開(kāi)始運(yùn)行,在自己的擴(kuò)容數(shù)組里面運(yùn)行:
e.next = newTable[i]; newTable[i] = e;
這個(gè)時(shí)候結(jié)構(gòu)圖:
然后e=next;
在進(jìn)入循環(huán)執(zhí)行:
e.next = newTable[i]; newTable[i] = e;
這個(gè)時(shí)候結(jié)構(gòu)為:
然后線程B執(zhí)行完畢。線程A開(kāi)始從(1)后面繼續(xù)執(zhí)行,這個(gè)時(shí)候也是先執(zhí)行
e.next = newTable[i]; newTable[i] = e;
然后e=next;這個(gè)時(shí)候e是節(jié)點(diǎn)6,然后再進(jìn)入循環(huán),執(zhí)行上面兩行程序后的結(jié)構(gòu)如下:
但是這個(gè)時(shí)候由于6的next是有值的,是節(jié)點(diǎn)5,所以再執(zhí)行e=next;的時(shí)候,e不為空,還會(huì)進(jìn)入一次循環(huán),在執(zhí)行將節(jié)點(diǎn)插入頭部的操作,所以這個(gè)時(shí)候的結(jié)構(gòu)圖:
可以,看到已經(jīng)成為了環(huán)狀鏈表,當(dāng)執(zhí)行g(shù)et操作的時(shí)候就會(huì)產(chǎn)生死循環(huán)。
到此這篇關(guān)于hashMap擴(kuò)容時(shí)應(yīng)該注意這些死循環(huán)問(wèn)題的文章就介紹到這了,更多相關(guān)hashMap擴(kuò)容內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring MVC3返回JSON數(shù)據(jù)中文亂碼問(wèn)題解決
本篇文章主要介紹了Spring MVC3返回JSON數(shù)據(jù)中文亂碼問(wèn)題解決,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01Spring Security其它權(quán)限校驗(yàn)方式&自定義權(quán)限校驗(yàn)方式
這篇文章主要介紹了Spring Security其它權(quán)限校驗(yàn)方式&自定義權(quán)限校驗(yàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08java servlet手機(jī)app訪問(wèn)接口(三)高德地圖云存儲(chǔ)及檢索
這篇文章主要為大家詳細(xì)介紹了java servlet手機(jī)app訪問(wèn)接口(三),高德地圖云存儲(chǔ)及檢索,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12基于Java實(shí)現(xiàn)一個(gè)自己的HTTP瀏覽器
這篇文章主要為大家詳細(xì)介紹了如何基于Java實(shí)現(xiàn)一個(gè)自己的HTTP瀏覽器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01SpringCloud中的OpenFeign調(diào)用解讀
OpenFeign是一個(gè)顯示聲明式的WebService客戶端,使用OpenFeign能讓編寫(xiě)Web Service客戶端更加簡(jiǎn)單OpenFeign的設(shè)計(jì)宗旨式簡(jiǎn)化Java Http客戶端的開(kāi)發(fā),本文給大家介紹SpringCloud之OpenFeign調(diào)用解讀,感興趣的朋友一起看看吧2023-11-11解決Error:(5, 28) java: 程序包org.apache.ibatis.io
這篇文章主要介紹了解決Error:(5, 28) java: 程序包org.apache.ibatis.io不存在問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05