日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

有沒有并發(fā)編程經(jīng)驗(yàn),一問這個(gè)類便知!

來源: 責(zé)編: 時(shí)間:2024-06-24 17:19:23 226觀看
導(dǎo)讀ThreadLocal能夠在線程本地存儲(chǔ)對應(yīng)的變量,從而有效的避免線程安全問題。但是使用ThreadLocal時(shí),稍微不注意就有可能造成內(nèi)存泄露的問題。那么ThreadLocal在哪些場景下會(huì)出現(xiàn)內(nèi)存泄露?哪些場景下不會(huì)出現(xiàn)內(nèi)存泄露?出現(xiàn)內(nèi)

ThreadLocal能夠在線程本地存儲(chǔ)對應(yīng)的變量,從而有效的避免線程安全問題。但是使用ThreadLocal時(shí),稍微不注意就有可能造成內(nèi)存泄露的問題。

那么ThreadLocal在哪些場景下會(huì)出現(xiàn)內(nèi)存泄露?哪些場景下不會(huì)出現(xiàn)內(nèi)存泄露?出現(xiàn)內(nèi)存泄露的根本原因又是什么呢?如何真正避免內(nèi)存泄露?5oL28資訊網(wǎng)——每日最新資訊28at.com

接下來,我們就用大量的圖解來分析ThreadLocal內(nèi)存泄露的四個(gè)核心問題:哪些場景不會(huì)內(nèi)存泄露、哪些場景會(huì)內(nèi)存泄露、內(nèi)存泄露的根本原因是什么、以及如何真正 避免內(nèi)存泄露。5oL28資訊網(wǎng)——每日最新資訊28at.com

一、ThreadLocal內(nèi)部結(jié)構(gòu)

為了更好的說明ThreadLocal內(nèi)存泄露的場景,以及具體的原因,先來了解下ThreadLocal的內(nèi)部結(jié)構(gòu),如圖1所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

5oL28資訊網(wǎng)——每日最新資訊28at.com

可以看到,ThreadLocal對象是存儲(chǔ)在每個(gè)Thread線程內(nèi)部的ThreadLocalMap中的,并且在ThreadLocalMap中有一個(gè)Entry數(shù)組,Entry數(shù)組中的每一個(gè)元素都是一個(gè)Entry對象。5oL28資訊網(wǎng)——每日最新資訊28at.com

每個(gè)Entry對象中存儲(chǔ)著一個(gè)ThreadLocal對象與其對應(yīng)的value值,每個(gè)Entry對象在Entry數(shù)組中的位置是通過ThreadLocal對象的threadLocalHashCode計(jì)算出來的,以此來快速定位Entry對象在Entry數(shù)組中的位置。5oL28資訊網(wǎng)——每日最新資訊28at.com

所以,在Thread中,可以存儲(chǔ)多個(gè)ThreadLocal對象。5oL28資訊網(wǎng)——每日最新資訊28at.com

二、不會(huì)出現(xiàn)內(nèi)存泄露的場景

了解完ThreadLocal的內(nèi)部存儲(chǔ)結(jié)構(gòu)后,我們先來思考下哪些場景下ThreadLocal不會(huì)發(fā)生內(nèi)存泄露,假設(shè)我們單獨(dú)開啟一個(gè)線程,并且將變量存儲(chǔ)到ThreadLocal中,如圖2所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

可以看到,Thread線程在正常執(zhí)行的情況下,會(huì)引用ThreadLocalMap的實(shí)例對象,只要Thread線程一直在執(zhí)行任務(wù),這種引用關(guān)系就一直存在。5oL28資訊網(wǎng)——每日最新資訊28at.com

當(dāng)Thread線程執(zhí)行任務(wù)結(jié)束退出時(shí),Thread線程與ThreadLocalMap實(shí)例對象之間的引用關(guān)系就不存在了,如圖3所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

Thread線程執(zhí)行完任務(wù)退出后,線程里持有的ThreadLocalMap對象也就失去了強(qiáng)引用,此時(shí)ThreadLocalMap對象就會(huì)被GC自動(dòng)回收,而ThreadLocalMap中包含的ThreadLocal對象也會(huì)被GC回收掉,如圖4所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

可以看出,如果只是通過Thread類或者Thread類的子類來創(chuàng)建線程執(zhí)行任務(wù),隨著對應(yīng)線程的任務(wù)執(zhí)行完畢,線程退出,Thread線程引用的ThreadLocal也會(huì)被GC回收掉,此時(shí)就不會(huì)出現(xiàn)內(nèi)存泄露的問題。5oL28資訊網(wǎng)——每日最新資訊28at.com

三、會(huì)出現(xiàn)內(nèi)存泄露的場景

在實(shí)際項(xiàng)目中,如果為每個(gè)任務(wù)的執(zhí)行都開啟一個(gè)線程的話,是非常耗費(fèi)系統(tǒng)資源的,所以,在實(shí)際項(xiàng)目中,我們很少直接使用Thread類來創(chuàng)建線程,而是使用線程池來執(zhí)行對應(yīng)的任務(wù)。5oL28資訊網(wǎng)——每日最新資訊28at.com

如果是在線程池場景下,線程與ThreadLocalMap之間的引用關(guān)系又是怎樣的呢?這里,我們先來看一張圖,如圖5所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

可以看到,線程池中會(huì)有多個(gè)線程執(zhí)行任務(wù),如果是通過ThreadLocal存儲(chǔ)數(shù)據(jù)的話,每個(gè)線程都會(huì)引用一個(gè)ThreadLocalMap對象。5oL28資訊網(wǎng)——每日最新資訊28at.com

另外,線程池中的核心線程在執(zhí)行完任務(wù)后,是不會(huì)退出的,可以循環(huán)使用,說明線程池中的每個(gè)核心線程和ThreadLocalMap之間一直是強(qiáng)引用關(guān)系,核心線程對應(yīng)的ThreadLocal是不會(huì)自動(dòng)被GC回收的,會(huì)存在內(nèi)存泄露的風(fēng)險(xiǎn)。5oL28資訊網(wǎng)——每日最新資訊28at.com

四、內(nèi)存泄露問題分析

這里,我們對在線程池中使用ThreadLocal存在內(nèi)存泄露問題的原因進(jìn)行分析,首先,將ThreadLocalMap中的Entry數(shù)組展開,如圖6所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

可以看到,ThreadLocalMap中包含一個(gè)Entry數(shù)組,而Entry數(shù)組中的每一個(gè)元素就是Entry對象,Entry對象中存儲(chǔ)的Key就是ThreadLocal對象,而value就是要存儲(chǔ)的數(shù)據(jù)。5oL28資訊網(wǎng)——每日最新資訊28at.com

其中,Entry對象中的Key屬于弱引用,這點(diǎn)我們可以從ThreadLocalMap類中的內(nèi)部類Entry的定義可以看出。Entry類的源碼詳見:java.lang.ThreadLocal.ThreadLocalMap.Entry。5oL28資訊網(wǎng)——每日最新資訊28at.com

static class Entry extends WeakReference<ThreadLocal<?>> {    /** The value associated with this ThreadLocal. */    Object value;    Entry(ThreadLocal<?> k, Object v) {        super(k);        value = v;    }}

可以看到,Entry類繼承了WeakReference類,WeakReference類的泛型是ThreadLocal,,說明ThreadLocalMap中的Entry數(shù)組對Entry對象的Key就是弱引用。5oL28資訊網(wǎng)——每日最新資訊28at.com

所以,Entry對象中的Key可以被GC自動(dòng)回收。當(dāng)Entry對象中的Key被GC自動(dòng)回收后如圖7所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

當(dāng)Entry對象中的Key被GC自動(dòng)回收后,對應(yīng)的ThreadLocal被GC回收掉了,變成了null,但是ThreadLocal對應(yīng)的value值依然被Entry引用,不能被GC自動(dòng)回收,如圖8所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

此時(shí),我們可以看到,Entry對象中的Key,也就是ThreadLocal對象可以被GC自動(dòng)回收,但是對應(yīng)的value還在被引用,所以,value是不能被GC自動(dòng)回收的,這種情況下就會(huì)存在內(nèi)存泄露的風(fēng)險(xiǎn)。5oL28資訊網(wǎng)——每日最新資訊28at.com

我們再來總結(jié)下,在線程池中使用ThreadLocal保存數(shù)據(jù)存在內(nèi)存泄露風(fēng)險(xiǎn)的原因:線程池中的核心線程會(huì)被循環(huán)使用,每個(gè)線程中對應(yīng)的ThreadLocalMap會(huì)被線程強(qiáng)引用。5oL28資訊網(wǎng)——每日最新資訊28at.com

所以,每個(gè)線程對應(yīng)的ThreadLocalMap不能被GC自動(dòng)回收。而ThreadLocalMap中包含一個(gè)Entry數(shù)組,Entry數(shù)組中含有多個(gè)Key為ThreadLocal,value為存儲(chǔ)的數(shù)據(jù)的Entry對象。5oL28資訊網(wǎng)——每日最新資訊28at.com

雖然Entry對象中的Key是弱引用,能夠被GC自動(dòng)回收,但是value卻是強(qiáng)引用,不能被GC自動(dòng)回收,所以,在線程池中使用ThreadLocal會(huì)存在內(nèi)存泄露的風(fēng)險(xiǎn)。5oL28資訊網(wǎng)——每日最新資訊28at.com

五、如何避免內(nèi)存泄露

在線程池中使用ThreadLocal如何避免內(nèi)存泄露呢?ThreadLocal提供相應(yīng)的解決方法了嗎?這里,我們就從ThreadLocal的源碼中看看ThreadLocal是否提供了對應(yīng)的解決方案。5oL28資訊網(wǎng)——每日最新資訊28at.com

在ThreadLocal中,提供了一個(gè)remove()方法,源碼詳見:java.lang.ThreadLocal#remove。5oL28資訊網(wǎng)——每日最新資訊28at.com

public void remove() {    ThreadLocalMap m = getMap(Thread.currentThread());    if (m != null)        m.remove(this);}

可以看到,在remove()方法中,首先根據(jù)當(dāng)前線程獲取ThreadLocalMap類型的m對象,不為空,則直接調(diào)用m對象的有參remove()方法移除value的值。5oL28資訊網(wǎng)——每日最新資訊28at.com

有參remove()方法的源碼詳見:java.lang.ThreadLocal.ThreadLocalMap#remove。5oL28資訊網(wǎng)——每日最新資訊28at.com

private void remove(ThreadLocal<?> key) {    Entry[] tab = table;    int len = tab.length;    int i = key.threadLocalHashCode & (len-1);    for (Entry e = tab[i];         e != null;         e = tab[i = nextIndex(i, len)]) {        if (e.get() == key) {            e.clear();            expungeStaleEntry(i);            return;        }    }}

可以看到,在有參remove()方法中,會(huì)通過threadLocalHashCode計(jì)算出Entry對象在Entry數(shù)組中的位置,并獲取出對應(yīng)的Entry對象。5oL28資訊網(wǎng)——每日最新資訊28at.com

如果Entry對象不為空,并且Entry對象中的Key等于傳入的ThreadLocal對象,則清除對應(yīng)的Key,并且調(diào)用expungeStaleEntry()方法。5oL28資訊網(wǎng)——每日最新資訊28at.com

接下來,我們再分析下expungeStaleEntry()方法,源碼詳見:java.lang.ThreadLocal.ThreadLocalMap#expungeStaleEntry。5oL28資訊網(wǎng)——每日最新資訊28at.com

private int expungeStaleEntry(int staleSlot) {    Entry[] tab = table;    int len = tab.length;    // expunge entry at staleSlot    tab[staleSlot].value = null;    tab[staleSlot] = null;    size--;    // Rehash until we encounter null    Entry e;    int i;    for (i = nextIndex(staleSlot, len);         (e = tab[i]) != null;         i = nextIndex(i, len)) {        ThreadLocal<?> k = e.get();        if (k == null) {            e.value = null;            tab[i] = null;            size--;        } else {            int h = k.threadLocalHashCode & (len - 1);            if (h != i) {                tab[i] = null;                // Unlike Knuth 6.4 Algorithm R, we must scan until                // null because multiple entries could have been stale.                while (tab[h] != null)                    h = nextIndex(h, len);                tab[h] = e;            }        }    }    return i;}

可以看到,在expungeStaleEntry()方法中,會(huì)將ThreadLocal為null對應(yīng)的value設(shè)置為null,同時(shí)會(huì)把對應(yīng)的Entry對象也設(shè)置為null,并且會(huì)將所有ThreadLocal對應(yīng)的value為null的Entry對象設(shè)置為null。5oL28資訊網(wǎng)——每日最新資訊28at.com

這樣就去除了強(qiáng)引用,便于后續(xù)的GC進(jìn)行自動(dòng)垃圾回收,也就避免了內(nèi)存泄露的問題。調(diào)用ThreadLocal的remove()方法后的示意圖如圖9所示。5oL28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片5oL28資訊網(wǎng)——每日最新資訊28at.com

注意:在ThreadLocal中,不僅僅是remove()方法會(huì)調(diào)用expungeStaleEntry()方法,在set()方法和get()方法中也可能會(huì)調(diào)用expungeStaleEntry()方法來清理數(shù)據(jù)。5oL28資訊網(wǎng)——每日最新資訊28at.com

還有一點(diǎn)需要注意的是,ThreadLocal雖然提供了避免內(nèi)存泄露的方法,但是ThreadLocal不會(huì)主動(dòng)去執(zhí)行這些方法,需要我們在使用完ThreadLocal對象中保存的數(shù)據(jù)后,在finally{}代碼塊中調(diào)用ThreadLocal的remove()方法,加快GC自動(dòng)垃圾回收,避免內(nèi)存泄露。5oL28資訊網(wǎng)——每日最新資訊28at.com

六、總結(jié)

本文,主要結(jié)合圖例介紹了ThreadLocal有關(guān)內(nèi)存泄露方面的知識(shí),包括:ThreadLocal的內(nèi)部結(jié)構(gòu),不會(huì)出現(xiàn)內(nèi)存泄露的場景,會(huì)出現(xiàn)內(nèi)存泄露的場景,內(nèi)存泄露的問題分析以及如何避免內(nèi)存泄露。5oL28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-96059-0.html有沒有并發(fā)編程經(jīng)驗(yàn),一問這個(gè)類便知!

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 秒懂雙親委派機(jī)制

下一篇: 開源的 15 個(gè)優(yōu)秀 C# 項(xiàng)目及示例代碼

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
国产精品三级久久久久久电影| 亚洲欧美日韩国产综合精品二区| 国产亚洲综合精品| 国产色爱av资源综合区| 亚洲第一伊人| 日韩视频在线播放| 亚洲综合色自拍一区| 久久久久综合网| 欧美激情亚洲精品| 国产精品国产三级国产aⅴ浪潮| 国产三级欧美三级日产三级99| 亚洲国产一区在线| 亚洲欧美在线免费观看| 麻豆精品精华液| 欧美视频在线观看视频极品| 国产在线播放一区二区三区| 亚洲精品老司机| 欧美一区二粉嫩精品国产一线天| 免费不卡在线观看| 国产精品一区二区在线| 亚洲电影在线看| 亚洲欧美日本在线| 欧美顶级大胆免费视频| 国产欧美一区二区精品性| 亚洲日本电影在线| 久久成人免费电影| 欧美日韩一二区| 在线观看欧美视频| 亚洲免费网址| 欧美精品一区二区三区久久久竹菊 | 日韩视频免费观看| 久久中文欧美| 国产精品影视天天线| 亚洲精品日韩在线观看| 久久高清国产| 国产精品video| 亚洲国产专区校园欧美| 久久成人av少妇免费| 欧美四级在线观看| 亚洲福利久久| 久久福利电影| 国产精品久久久亚洲一区| 亚洲激情影视| 久久久久久国产精品mv| 国产精品人成在线观看免费| 亚洲乱码久久| 免费成人高清| 国产综合激情| 亚洲欧美亚洲| 欧美日韩一区二区三区高清| 亚洲区国产区| 美女精品自拍一二三四| 黑丝一区二区三区| 新狼窝色av性久久久久久| 欧美无乱码久久久免费午夜一区| 亚洲精品123区| 久久久久久久欧美精品| 国产欧美短视频| 亚洲小说欧美另类社区| 欧美日韩另类丝袜其他| 91久久久一线二线三线品牌| 久久全国免费视频| 国内偷自视频区视频综合| 欧美亚洲一区二区三区| 国产精品入口66mio| 亚洲午夜极品| 国产精品高潮呻吟久久| 亚洲视频一区二区在线观看 | 欧美岛国在线观看| 在线观看欧美一区| 久久婷婷亚洲| 激情文学综合丁香| 久久久亚洲精品一区二区三区| 在线看片第一页欧美| 久久久久国产精品麻豆ai换脸| 国产亚洲综合在线| 久久国产精品久久国产精品| 国产视频一区在线| 久久成人羞羞网站| 国内偷自视频区视频综合| 欧美综合二区| 国产亚洲永久域名| 久久久久久久国产| 在线观看国产精品网站| 蜜桃av一区二区三区| 亚洲韩日在线| 欧美精品一级| 一区二区三区日韩| 欧美调教vk| 亚洲欧美日韩第一区| 国产一区二区三区在线观看精品 | 亚洲欧美日韩系列| 国产情人综合久久777777| 久久av一区二区| 国产一区二区剧情av在线| 久久久久久电影| 亚洲国产日韩欧美在线图片| 欧美久久久久久久久| 亚洲视频一二三| 国产精品美女久久久免费| 欧美一级久久久| 激情综合色综合久久| 欧美国产日韩一区二区| 一区二区av| 国产欧美精品国产国产专区| 久久在线免费视频| 夜久久久久久| 国产精品少妇自拍| 久久久久久噜噜噜久久久精品| 亚洲高清资源综合久久精品| 欧美日韩高清不卡| 午夜精品福利一区二区蜜股av| 国产亚洲欧美色| 欧美成人亚洲| 亚洲一区二区三区四区五区黄| 国产日韩在线看| 久久综合中文字幕| 99国产精品视频免费观看一公开| 国产精品视频导航| 久久久精品国产免大香伊| 亚洲欧洲一区二区三区久久| 欧美亚日韩国产aⅴ精品中极品| 久久av老司机精品网站导航| 亚洲精品一区二区三区蜜桃久| 国产精品视频你懂的| 久久在线精品| 亚洲图片欧洲图片av| 合欧美一区二区三区| 欧美日韩在线播放| 久久深夜福利| 亚洲小视频在线| 亚洲国产精品一区| 国产精品美女一区二区| 欧美jizz19性欧美| 午夜精品亚洲一区二区三区嫩草| 亚洲国产精品久久| 国产九色精品成人porny| 欧美大片在线观看| 欧美一区二区三区在线播放| 亚洲精品一区二区三区av| 国产一区二区三区奇米久涩| 欧美伦理a级免费电影| 久久精品国产精品亚洲| 一本大道久久精品懂色aⅴ| 国内精品视频在线播放| 欧美日韩国产探花| 久久视频免费观看| 午夜精品久久久久久久久| 日韩午夜av在线| 激情欧美一区二区| 国产精品免费网站| 欧美精品一区二| 久久青青草综合| 欧美一区二区三区成人| 一区二区三区四区五区视频| 亚洲第一在线综合网站| 国产日韩欧美一区二区| 欧美午夜精品一区| 欧美国产综合一区二区| 久久久久这里只有精品| 亚洲欧美日韩在线播放| 一本色道久久综合狠狠躁篇的优点 | 久久人人97超碰国产公开结果 | 一本到高清视频免费精品| 在线观看国产一区二区| 国产午夜精品一区理论片飘花| 欧美视频一区二区三区…| 欧美激情精品久久久久久黑人| 久久精品亚洲| 亚洲欧洲av一区二区| 制服丝袜亚洲播放| 日韩视频一区二区| 亚洲黄色高清| 在线电影一区| 韩日精品视频| 国产一区二区毛片| 国产日韩欧美一区| 国产精品久久久久久亚洲毛片 | 国产精品久线观看视频| 欧美日韩不卡合集视频| 欧美成人免费va影院高清| 久久久一区二区| 久久久久看片| 久久久噜噜噜久久| 欧美中文在线观看国产| 欧美一区二区三区在线看 | 蜜月aⅴ免费一区二区三区| 久久久精品国产一区二区三区 | 欧美精品一区二区三区蜜臀| 葵司免费一区二区三区四区五区| 欧美专区日韩视频| 欧美在线播放一区| 校园激情久久| 欧美一区二区三区免费视| 午夜一区二区三区不卡视频| 亚洲女ⅴideoshd黑人| 亚洲在线网站| 亚洲欧美日本国产有色| 午夜国产精品影院在线观看 | 亚洲欧美日韩天堂一区二区| 性欧美大战久久久久久久久| 午夜综合激情| 久久国产婷婷国产香蕉| 久久久久91|