日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
ThreadLocal真的會(huì)造成內(nèi)存泄漏嗎?

ThreadLoca在并發(fā)場(chǎng)景中,應(yīng)用非常多。前幾天有位小伙伴問(wèn)我一個(gè)問(wèn)題,說(shuō)ThreadLocal是不是真的會(huì)造成內(nèi)存泄漏?今天給大家做一個(gè)分享。

成都創(chuàng)新互聯(lián)專注于寬城企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,電子商務(wù)商城網(wǎng)站建設(shè)。寬城網(wǎng)站建設(shè)公司,為寬城等地區(qū)提供建站服務(wù)。全流程專業(yè)公司,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

1、ThreadLocal的基本原理

考慮到很多小伙伴可能還不太了解ThreadLocal,我先簡(jiǎn)單介紹一下ThreadLocal。在多線程并發(fā)訪問(wèn)同一個(gè)共享變量的情況下,如果不做同步控制的話,就可能會(huì)導(dǎo)致數(shù)據(jù)不一致的問(wèn)題,所以,我們需要使用synchronized加鎖來(lái)解決。

而ThreadLocal換了一個(gè)思路來(lái)處理多線程的情況。

ThreadLocal本身并不存儲(chǔ)數(shù)據(jù),它使用了線程中的threadLocals屬性,threadLocals的類型就是在ThreadLocal中的定義的ThreadLocalMap對(duì)象,當(dāng)調(diào)用ThreadLocal的set(T value)方法時(shí),ThreadLocal將自身的引用也就是this作為Key,然后,把用戶傳入的值作為Value存儲(chǔ)到線程的ThreadLocalMap中,這就相當(dāng)于每個(gè)線程的讀寫操作都是基于線程自身的一個(gè)私有副本,線程之間的數(shù)據(jù)是相互隔離的,互不影響。

這樣一來(lái)基于ThreadLocal的操作也就不存在線程安全問(wèn)題了。它相當(dāng)于采用了用空間來(lái)?yè)Q時(shí)間的思路,從而提高程序的執(zhí)行效率。

2、四種對(duì)象引用

在ThreadLocalMap內(nèi)部,維護(hù)了一個(gè)Entry數(shù)組table的屬性,用來(lái)存儲(chǔ)鍵值對(duì)的映射關(guān)系,來(lái)看這樣一段代碼片段:

static class ThreadLocalMap {
...
private Entry[] table;
static class Entry implements WeakReference> {
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
...
}

Entry將ThreadLocal作為Key,值作為Value保存,它繼承自WeakReference,注意構(gòu)造函數(shù)里的第一行代碼super(k),這意味著ThreadLocal對(duì)象是一個(gè)「弱引用」。有的小伙伴可能對(duì)「弱引用」不太熟悉,這里再介紹一下Java的四種引用關(guān)系。

在JDK1.2之后,Java對(duì)引用的概念做了一些擴(kuò)充,將引用分為“強(qiáng)”、“軟”、“弱”、“虛”四種,由強(qiáng)到弱依次為:

強(qiáng)引用:指代碼中普遍存在的賦值行為,如:Object o = new Object(),只要強(qiáng)引用關(guān)系還在,對(duì)象就永遠(yuǎn)不會(huì)被回收。

軟引用:還有用處,但不是必須存活的對(duì)象,JVM會(huì)在內(nèi)存溢出前對(duì)其進(jìn)行回收,例如:緩存。

弱引用:非必須存活的對(duì)象,引用關(guān)系比軟引用還弱,不管內(nèi)存是否夠用,下次GC一定回收。

虛引用:也稱“幽靈引用”、“幻影引用”,最弱的引用關(guān)系,完全不影響對(duì)象的回收,等同于沒(méi)有引用,虛引用的唯一的目的是對(duì)象被回收時(shí)會(huì)收到一個(gè)系統(tǒng)通知。

這個(gè)描述還是比較官方的,簡(jiǎn)單總結(jié)一下,大家應(yīng)該都追過(guò)劇,強(qiáng)引用就好比是男主角,怎么都死不了。軟引用就像女主角,雖有一段經(jīng)歷,還是沒(méi)走到最后。弱引用就是男二號(hào),注定用來(lái)犧牲的。虛引用就是路人甲了。

3、造成內(nèi)存泄漏的原因

內(nèi)存泄漏和ThreadLocalMap中定義的Entry類有非常大的關(guān)系。

這個(gè)動(dòng)畫完整地展示了ThreadLocal中對(duì)象引用的關(guān)系,需要這張高清圖的小伙伴可以在評(píng)論區(qū)留言。

由于ThreadLocal對(duì)象是弱引用,如果外部沒(méi)有強(qiáng)引用指向它,它就會(huì)被GC回收,導(dǎo)致Entry的Key為空(null),如果這時(shí)Value外部也沒(méi)有強(qiáng)引用指向它,那么Value就永遠(yuǎn)也訪問(wèn)不到了,按理也應(yīng)該被GC回收,但是由于Entry對(duì)象還在強(qiáng)引用Value,導(dǎo)致Value無(wú)法被回收,這時(shí)「內(nèi)存泄漏」就發(fā)生了,Value成了一個(gè)永遠(yuǎn)也無(wú)法被訪問(wèn),但是又無(wú)法被回收的對(duì)象。

Entry對(duì)象屬于ThreadLocalMap,ThreadLocalMap又屬于Thread,如果線程本身的生命周期很短,短時(shí)間內(nèi)就會(huì)被銷毀,那么「內(nèi)存泄漏」立刻就會(huì)得到解決,只要線程被銷毀,Value也會(huì)隨之被回收。

問(wèn)題是,線程本身是非常珍貴的計(jì)算機(jī)資源,很少會(huì)去頻繁的創(chuàng)建和銷毀,一般都是通過(guò)線程池來(lái)使用,這就將線程的生命周期大大拉長(zhǎng),「內(nèi)存泄漏」的影響也會(huì)越來(lái)越大。

最后,一句話總結(jié)一下。

threadLocals對(duì)象中的Entry對(duì)象不再使用后,如果沒(méi)有及時(shí)清除Entry對(duì)象 ,而程序自身也無(wú)法通過(guò)垃圾回收機(jī)制自動(dòng)清除,就可能導(dǎo)致內(nèi)存泄漏。

4、如何避免內(nèi)存泄漏?

不要聽(tīng)到「內(nèi)存泄漏」就不敢使用ThreadLocal,只要規(guī)范化使用是不會(huì)有問(wèn)題的。我給大家支幾個(gè)招:

  1. 每次使用完ThreadLocal都記得調(diào)用remove()方法清除數(shù)據(jù)。
  2. 將ThreadLocal變量盡可能地定義成static final,避免頻繁創(chuàng)建ThreadLocal實(shí)例。這樣也就保證程序一直存在ThreadLocal的強(qiáng)引用,也能保證任何時(shí)候都能通過(guò)ThreadLocal的弱引用訪問(wèn)到Entry的Value值,進(jìn)而清除掉。

當(dāng)然,就是使用不規(guī)范,ThreadLocal內(nèi)部也做了一些優(yōu)化,比如:

  1. 調(diào)用set()方法時(shí),ThreadLocal會(huì)進(jìn)行采樣清理、全量清理,擴(kuò)容時(shí)還會(huì)繼續(xù)檢查。
  2. 調(diào)用get()方法時(shí),如果沒(méi)有直接命中或者向后環(huán)形查找時(shí)也會(huì)進(jìn)行清理。
  3. 調(diào)用remove()時(shí),除了清理當(dāng)前Entry,還會(huì)向后繼續(xù)清理。

當(dāng)前文章:ThreadLocal真的會(huì)造成內(nèi)存泄漏嗎?
文章網(wǎng)址:http://www.dlmjj.cn/article/dhjcdgd.html