大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動(dòng)力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 HashMap死循環(huán):HashMap Infinite Loop

HashMap死循環(huán):HashMap Infinite Loop

更新時(shí)間:2021-10-22 10:38:05 來源:動(dòng)力節(jié)點(diǎn) 瀏覽900次

問題的癥狀

從前我們的Java代碼因?yàn)橐恍┰蚴褂昧薍ashMap這個(gè)東西,但是當(dāng)時(shí)的程序是單線程的,一切都沒有問題。后來,我們的程序性能有問題,所以需要變成多線程的,于是,變成多線程后到了線上,發(fā)現(xiàn)程序經(jīng)常占了100%的CPU,查看堆棧,你會發(fā)現(xiàn)程序都Hang在了HashMap.get()這個(gè)方法上了,重啟程序后問題消失。但是過段時(shí)間又會來。而且,這個(gè)問題在測試環(huán)境里可能很難重現(xiàn)。

Hash表數(shù)據(jù)結(jié)構(gòu)

HashMap通常會用一個(gè)指針數(shù)組(假設(shè)為table[])來做分散所有的key,當(dāng)一個(gè)key被加入時(shí),會通過Hash算法通過key算出這個(gè)數(shù)組的下標(biāo)i,然后就把這個(gè)插到table[i]中,如果有兩個(gè)不同的key被算在了同一個(gè)i,那么就叫沖突,又叫碰撞,這樣會在table[i]上形成一個(gè)鏈表。

我們知道,如果table[]的尺寸很小,比如只有2個(gè),如果要放進(jìn)10個(gè)keys的話,那么碰撞非常頻繁,于是一個(gè)O(1)的查找算法,就變成了鏈表遍歷,性能變成了O(n),這是Hash表的缺陷。

所以,Hash表的尺寸和容量非常的重要。一般來說,Hash表這個(gè)容器當(dāng)有數(shù)據(jù)要插入時(shí),都會檢查容量有沒有超過設(shè)定的thredhold,如果超過,需要增大Hash表的尺寸,但是這樣一來,整個(gè)Hash表里的元素都需要被重算一遍。這叫rehash,這個(gè)成本相當(dāng)?shù)拇蟆?/p>

HashMap的rehash源代碼

Put一個(gè)Key,Value對到Hash表中:

public V put(K key, V value)
{
    ......
    //算Hash值
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    //如果該key已被插入,則替換掉舊的value (鏈接操作)
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }
    modCount++;
    //該key不存在,需要增加一個(gè)結(jié)點(diǎn)
    addEntry(hash, key, value, i);
    return null;
}

檢查容量是否超標(biāo)

void addEntry(int hash, K key, V value, int bucketIndex)
{
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
    //查看當(dāng)前的size是否超過了我們設(shè)定的閾值threshold,如果超過,需要resize
    if (size++ >= threshold)
        resize(2 * table.length);
}

新建一個(gè)更大尺寸的hash表,然后把數(shù)據(jù)從老的Hash表中遷移到新的Hash表中

void resize(int newCapacity)
{
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    ......
    //創(chuàng)建一個(gè)新的Hash Table
    Entry[] newTable = new Entry[newCapacity];
    //將Old Hash Table上的數(shù)據(jù)遷移到New Hash Table上
    transfer(newTable);
    table = newTable;
    threshold = (int)(newCapacity * loadFactor);
}
void transfer(Entry[] newTable)
{
    Entry[] src = table;
    int newCapacity = newTable.length;
    //下面這段代碼的意思是:
    //  從OldTable里摘一個(gè)元素出來,然后放到NewTable中
    for (int j = 0; j < src.length; j++) {
        Entry<K,V> e = src[j];
        if (e != null) {
            src[j] = null;
            do {
                Entry<K,V> next = e.next;
                int i = indexFor(e.hash, newCapacity);
                e.next = newTable[i];
                newTable[i] = e;
                e = next;
            } while (e != null);
        }
    }
}

以上就是關(guān)于“HashMap死循環(huán):HashMap Infinite Loop”的介紹,如果您想了解更多相關(guān)知識,可以關(guān)注一下動(dòng)力節(jié)點(diǎn)的Java基礎(chǔ)教程,里面的課程內(nèi)容全面細(xì)致,通俗易懂,適合初學(xué)者學(xué)習(xí),希望對大家能夠有所幫助。

提交申請后,顧問老師會電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 国产一级毛片欧美视频 | 国产一级淫 | 日韩免费观看一级毛片看看 | 国产 福利 在线 | 国产精品二 | 噜噜狠狠 | 717影院理论午夜伦八戒 | 99热成人精品国产免国语的 | 五月婷婷激情 | 91精品国产福利尤物免费 | 日韩一区二区三区中文字幕 | 国产在线欧美精品 | 国产激情小视频 | 久草视频免费 | 国产一国产一级毛片视频在线 | 欧美3区| 国产96福利视频在线观看 | 亚洲精品乱码国产精品乱码 | 四虎麻豆 | 中文字幕一区二区三区视频在线 | 免费h片在线观看网址最新 免费v片在线观看无遮挡 | 91精东果冻蜜桃星空麻豆 | 欧美xxxx成人免费视频 | 亚洲欧美在线综合一区二区三区 | 淫综合网 | 91精品国产一区二区三区左线 | 69精品久久久久 | 天天爽天天碰狠狠添 | 校园春色男人天堂 | 国产精品入口麻豆 | 国产成人综合网亚洲欧美在线 | 99国产大尺度福利视频 | 国产尤物精品视频 | 中文乱码在线观看 | 久久成人激情视频 | 亚洲激情视频在线播放 | 国产精品美女www爽爽爽视频 | 松永纱奈在线观看 | 伊人在综合| 欧美精品观看 | 亚洲精品欧洲久久婷婷99 |