日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
談?wù)勀銓hreadLocal的理解

思考:對ThreadLocal的理解多少?

成都創(chuàng)新互聯(lián)公司服務(wù)項目包括紅旗網(wǎng)站建設(shè)、紅旗網(wǎng)站制作、紅旗網(wǎng)頁制作以及紅旗網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,紅旗網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到紅旗省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

springboot葵花寶典

主要分享JAVA技術(shù),主要包含SpringBoot、SpingCloud、Docker、中間件等技術(shù),以及Github開源項目

1.ThreadLocal概述

ThreadLocal是多線程中對于解決線程安全的一個操作類,它會為每個線程都分配一個獨立的線程副本從而解決了變量并發(fā)訪問沖突的問題。ThreadLocal 同時實現(xiàn)了線程內(nèi)的資源共享

案例:使用JDBC操作數(shù)據(jù)庫時,會將每一個線程的Connection放入各自的ThreadLocal中,從而保證每個線程都在各自的 Connection 上進行數(shù)據(jù)庫的操作,避免A線程關(guān)閉了B線程的連接。

圖片

2. ThreadLocal的實現(xiàn)原理&源碼解析

ThreadLocal本質(zhì)來說就是一個線程內(nèi)部存儲類,從而讓多個線程只操作自己內(nèi)部的值,從而實現(xiàn)線程數(shù)據(jù)隔離

每個線程內(nèi)有一個 ThreadLocalMap 類型的成員變量,用來存儲資源對象

圖片

ThreadLocalMap 的一些特點

key 的 hash 值統(tǒng)一分配

初始容量 16,擴容因子 2/3,擴容容量翻倍

key 索引沖突后用開放尋址法解決沖突

2.1. ThreadLocal基本使用

set(value) 設(shè)置值:  以 ThreadLocal 自己作為 key,資源對象作為 value,放入當(dāng)前線程的 ThreadLocalMap 集合中

get() 獲取值: 以 ThreadLocal 自己作為 key,到當(dāng)前線程中查找關(guān)聯(lián)的資源值

remove() 清除值: 以 ThreadLocal 自己作為 key,移除當(dāng)前線程關(guān)聯(lián)的資源值

代碼案例

public class ThreadLocalTest {
    static ThreadLocal threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            threadLocal.set("zbbmeta");
            print(name);
            System.out.println(name + "-after remove : " + threadLocal.get());
        }, "t1").start();
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            threadLocal.set("zbbmeta");
            print(name);
            System.out.println(name + "-after remove : " + threadLocal.get());
        }, "t2").start();
    }

    static void print(String str) {
        //打印當(dāng)前線程中本地內(nèi)存中本地變量的值
        System.out.println(str + " :" + threadLocal.get());
        //清除本地內(nèi)存中的本地變量
        threadLocal.remove();
    }

}

3. ThreadLocal-內(nèi)存泄露問題

在介紹內(nèi)存泄露問題問題之前先介紹一下Java對象中的四種引用類型:Java對象中的四種引用類型:

  • 強引用: 最為普通的引用方式,表示一個對象處于有用且必須的狀態(tài),如果一個對象具有強引用,則GC并不會回收它。即便堆中內(nèi)存不足了,寧可出現(xiàn)OOM,也不會對其進行回收
Object obj = new Object();
  • 軟引用:軟引用用于描述一些還有用但并非必須保持的對象。在系統(tǒng)即將發(fā)生內(nèi)存溢出之前,垃圾收集器會清理這些軟引用指向的對象
Object obj = new Object();
SoftReference softRef = new SoftReference<>(obj);
  • 弱引用:表示一個對象處于可能有用且非必須的狀態(tài)。在GC線程掃描內(nèi)存區(qū)域時,一旦發(fā)現(xiàn)弱引用,就會回收到弱引用相關(guān)聯(lián)的對象。對于弱引用的回收,無關(guān)內(nèi)存區(qū)域是否足夠,一旦發(fā)現(xiàn)則會被回收
Object obj = new Object();
WeakReference weakRef = new WeakReference<>(obj);
  • 虛引用:虛引用也稱為幽靈引用,它幾乎沒有實際意義,主要用于跟蹤對象被垃圾收集的活動;虛引用不能單獨使用,必須與引用隊列(ReferenceQueue)一起使用。當(dāng)垃圾收集器準(zhǔn)備回收一個對象時,如果發(fā)現(xiàn)它有虛引用,會把這個虛引用加入到與之關(guān)聯(lián)的引用隊列中
Object obj = new Object();
PhantomReference phantomRef = new PhantomReference<>(obj, referenceQueue);

3.1. ThreadLocal-內(nèi)存泄露問題

每一個Thread維護一個ThreadLocalMap,在ThreadLocalMap中的Entry對象繼承了WeakReference,其中key為使用弱引用的ThreadLocal實例,value為線程變量的副本

圖片

ThreadLocalMap 中的 key 被設(shè)計為弱引用,原因如下

Thread 可能需要長時間運行(如線程池中的線程),如果 key 不再使用,需要在內(nèi)存不足(GC)時釋放其占用的內(nèi)存

內(nèi)存釋放時機

  • 被動 GC 釋放 key

僅是讓 key 的內(nèi)存釋放,關(guān)聯(lián) value 的內(nèi)存并不會釋放

  • 懶惰被動釋放 value
  • get key 時,發(fā)現(xiàn)是 null key,則釋放其 value 內(nèi)存
  • set key 時,會使用啟發(fā)式掃描,清除臨近的 null key 的 value 內(nèi)存,啟發(fā)次數(shù)與元素個數(shù),是否發(fā)現(xiàn) null key 有關(guān)
  • 主動 remove 釋放 key,value
  • 會同時釋放 key,value 的內(nèi)存,也會清除臨近的 null key 的 value 內(nèi)存
  • 推薦使用它,因為一般使用 ThreadLocal 時都把它作為靜態(tài)變量(即強引用),因此無法被動依靠 GC 回收

4. ThreadLocal面試題

面試官:談?wù)勀銓hreadLocal的理解

候選人:

ThreadLocal 主要功能有兩個:

  • 第一個是可以實現(xiàn)資源對象的線程隔離,讓每個線程各用各的資源對象,避免爭用引發(fā)的線程安全問題
  • 第二個是實現(xiàn)了線程內(nèi)的資源共享

面試官:好的,那你知道ThreadLocal的底層原理實現(xiàn)嗎?

候選人:

在ThreadLocal內(nèi)部維護了一個一個 ThreadLocalMap 類型的成員變量,用來存儲資源對象

當(dāng)我們調(diào)用 set 方法,就是以 ThreadLocal 自己作為 key,資源對象作為 value,放入當(dāng)前線程的 ThreadLocalMap 集合中

當(dāng)調(diào)用 get 方法,就是以 ThreadLocal 自己作為 key,到當(dāng)前線程中查找關(guān)聯(lián)的資源值

當(dāng)調(diào)用 remove 方法,就是以 ThreadLocal 自己作為 key,移除當(dāng)前線程關(guān)聯(lián)的資源值

面試官:好的,那關(guān)于ThreadLocal會導(dǎo)致內(nèi)存溢出這個事情,了解嗎?

候選人:

是應(yīng)為ThreadLocalMap 中的 key 被設(shè)計為弱引用,它是被動的被GC調(diào)用釋放key,不過關(guān)鍵的是只有key可以得到內(nèi)存釋放,而value不會,因為value是一個強引用。

在使用ThreadLocal 時都把它作為靜態(tài)變量(即強引用),因此無法被動依靠 GC 回收,建議主動的remove 釋放 key,這樣就能避免內(nèi)存溢出。


文章題目:談?wù)勀銓hreadLocal的理解
當(dāng)前路徑:http://m.5511xx.com/article/cogodig.html