偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

ThreadLocal最全詳解(萬字圖文總結(jié))

開發(fā) 前端
ThreadLocal提供了線程的本地變量,是 Java 中用于實(shí)現(xiàn)線程局部變量的類,它提供了線程內(nèi)部的獨(dú)立變量。即即每個(gè)線程都有一個(gè)獨(dú)立的"變量副本",不會(huì)與其他線程的"變量副本"產(chǎn)生沖突。

大家好,我是mikechen。

ThreadLocal是實(shí)現(xiàn)Java并發(fā)編程非常重要的一個(gè)組件,也是大廠喜歡考察的內(nèi)容,下面我就全面來詳解ThreadLocal@mikechen

ThreadLocal

ThreadLocal提供了線程的本地變量,是 Java 中用于實(shí)現(xiàn)線程局部變量的類,它提供了線程內(nèi)部的獨(dú)立變量。

即即每個(gè)線程都有一個(gè)獨(dú)立的"變量副本",不會(huì)與其他線程的"變量副本"產(chǎn)生沖突。

如下圖所示:

圖片圖片

每個(gè)線程都有自己的獨(dú)立資源,可以通過 ThreadLocal 對(duì)象訪問它自己的獨(dú)立變量。

ThreadLocal中填充的變量屬于當(dāng)前線程,該變量對(duì)其他線程而言是隔離的,也就是說該變量是當(dāng)前線程獨(dú)有的變量。

ThreadLocal主要用于:解決多線程并發(fā)時(shí)訪問共享變量的問題,主要是做數(shù)據(jù)隔離。

ThreadLocal原理

ThreadLocal原理:ThreadLocal相當(dāng)于維護(hù)了一個(gè)map,key就是當(dāng)前的線程,value就是需要存儲(chǔ)的對(duì)象。

這個(gè) Map 不是直接使用 HashMap ,而是 ThreadLocal 實(shí)現(xiàn)的一個(gè)叫做 ThreadLocalMap 的靜態(tài)內(nèi)部類,用來存變量。

它的大概結(jié)構(gòu)如下圖所示:

圖片圖片

ThreadLocalMap

ThreadLocalMap 是 ThreadLocal 的核心存儲(chǔ)結(jié)構(gòu),類似于 HashMap,但設(shè)計(jì)上有所不同:

ThreadLocalMap 是 ThreadLocal 的內(nèi)部靜態(tài)類,是一個(gè)自定義的哈希表,專門用于存儲(chǔ)與 ThreadLocal 關(guān)聯(lián)的數(shù)據(jù)。

每個(gè)線程都持有一個(gè) ThreadLocalMap 實(shí)例,以存儲(chǔ)它的 ThreadLocal 變量和對(duì)應(yīng)的值。

ThreadLocalMap是一個(gè)Map,key是ThreadLocal,value是Object。

Entry 類

除此之外,ThreadLocalMap內(nèi)部持有一個(gè) Entry[] 類型的數(shù)組 table,每個(gè)數(shù)組成員都是一個(gè)鍵值對(duì),Entry數(shù)組是真正承載數(shù)據(jù)的地方。

ThreadLocalMap.Entry 繼承自 Java 標(biāo)準(zhǔn)庫中的 WeakReference<ThreadLocal<?>>,它的核心結(jié)構(gòu)如下:

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;
    //key就是一個(gè)弱引用
    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

Entry繼承自WeakReference,每個(gè)Entry 的 key 都是一個(gè) ThreadLocal 對(duì)象的弱引用,Java 中的弱引用允許對(duì)一個(gè)對(duì)象的引用在沒有強(qiáng)引用的情況下,被垃圾回收器回收。

value 是Object 類型,是強(qiáng)引用,ThreadLocalMap 中可以包含多個(gè)ThreadLocal對(duì)象。

如下圖所示:

圖片圖片

ThreadLocalMap中包含了多個(gè)ThreadLocal對(duì)象,那么如果一個(gè)線程使用多個(gè)ThreadLocal對(duì)象,ThreadLocalMap如何區(qū)分不同的ThreadLocal呢?

實(shí)際上,每一個(gè)ThreadLocal對(duì)象都包含了一個(gè)獨(dú)一無二的threadLocalHashCode值,使用這個(gè)值就可以在KV數(shù)組中找到對(duì)應(yīng)的本地變量。

圖片圖片

key是ThreadLocal對(duì)象的弱引用,之所以使用 WeakReference 類型作為ThreadLocal對(duì)象的引用,是出于垃圾回收考慮。

不過需要注意的是,雖然key值是弱引用,不影響ThreadLocal對(duì)象回收,但value值是強(qiáng)引用。

當(dāng)ThreadLocal被回收,value對(duì)象不會(huì)被回收,可能會(huì)引發(fā)內(nèi)存泄漏。

所以,記得要調(diào)用 remove() 方法,避免內(nèi)存泄露。

ThreadLocal使用

ThreadLocal的用法,這個(gè)類提供thread-local變量,這些變量與線程的局部變量不同,每個(gè)線程都保存一份改變量的副本,可以通過get、或者set方法訪問。

如下所示:

//創(chuàng)建
private ThreadLocal threadLocal = new ThreadLocal();
//一旦創(chuàng)建了ThreadLocal,就可以使用它的set()方法設(shè)置要存儲(chǔ)在其中的值
threadLocal.set("A thread local value");
//獲取值
String threadLocalValue = (String) threadLocal.get();
//移除一個(gè)值
threadLocal.remove();

ThreadLocal提供了線程內(nèi)存儲(chǔ)變量的能力,這些變量不同之處在于每一個(gè)線程讀取的變量是對(duì)應(yīng)的互相獨(dú)立的,通過get和set方法就可以得到當(dāng)前線程對(duì)應(yīng)的值。

由于ThreadLocal里設(shè)置的值,只有當(dāng)前線程自己看得見,這意味著你不可能通過其他線程為它初始化值,為了彌補(bǔ)這一點(diǎn),ThreadLocal提供了一個(gè)withInitial()方法統(tǒng)一初始化所有線程的ThreadLocal的值。

如下所示:

private ThreadLocal<Integer> localInt = ThreadLocal.withInitial(() -> 18);

上述代碼將ThreadLocal的初始值設(shè)置為18,這對(duì)全體線程都是可見的。

ThreadLocal應(yīng)用

在通常的業(yè)務(wù)開發(fā)中,ThreadLocal 有以下3種典型的使用場(chǎng)景:

圖片圖片

1.解決線程安全問題

ThreadLocal 用作保存每個(gè)線程獨(dú)享的對(duì)象,為每個(gè)線程都創(chuàng)建一個(gè)副本,這樣每個(gè)線程都可以修改自己所擁有的副本, 而不會(huì)影響其他線程的副本,確保了線程安全。

2.代替參數(shù)的顯式傳遞

當(dāng)我們?cè)趯慉PI接口的時(shí)候,通常Controller層會(huì)接受來自前端的入?yún)ⅰ?/p>

當(dāng)這個(gè)接口功能比較復(fù)雜的時(shí)候,通常情況下,我們會(huì)在每個(gè)調(diào)用的方法上加上需要傳遞的參數(shù)。

但是,如果我們將參數(shù)存入ThreadLocal中,那么就不用顯式的傳遞參數(shù)了,而是只需要ThreadLocal中獲取即可。

這是因?yàn)椋菏褂脜?shù)傳遞造成代碼的耦合度高,使用靜態(tài)全局變量在多線程環(huán)境下不安全,當(dāng)該對(duì)象用ThreadLocal包裝過后,就可以保證在該線程中獨(dú)此一份,同時(shí)和其他線程隔離。

比如:在Spring的@Transaction事務(wù)聲明的注解中,就使用ThreadLocal保存了當(dāng)前的Connection對(duì)象,避免在本次調(diào)用的不同方法中使用不同的Connection對(duì)象。

3.全局存儲(chǔ)用戶信息

可以嘗試使用ThreadLocal替代Session的使用,每個(gè)線程擁有獨(dú)立的 Session 對(duì)象。

當(dāng)用戶要訪問需要授權(quán)的接口的時(shí)候,可以現(xiàn)在攔截器中將用戶的Token存入ThreadLocal中,之后在本次訪問中任何需要用戶用戶信息的都可以直接沖ThreadLocal中拿取數(shù)據(jù)。

責(zé)任編輯:武曉燕 來源: mikechen的互聯(lián)網(wǎng)架構(gòu)
相關(guān)推薦

2024-12-31 00:00:01

驅(qū)動(dòng)設(shè)計(jì)應(yīng)用場(chǎng)景業(yè)務(wù)邏輯

2024-09-26 13:33:12

2024-08-30 10:29:21

2024-09-04 09:43:36

2024-07-26 10:35:00

2023-10-31 12:58:00

TypeScriptJavaScript

2021-03-16 08:21:29

Spark系統(tǒng)并行

2024-05-31 13:34:57

2024-08-29 10:23:42

2024-08-08 13:01:53

2022-09-06 08:02:40

死鎖順序鎖輪詢鎖

2020-03-18 12:47:59

設(shè)計(jì)模式ERP

2024-08-12 16:09:31

2020-01-15 09:53:59

MySQL緩存索引

2024-05-10 12:59:58

PyTorch人工智能

2021-03-18 10:04:46

數(shù)據(jù)倉庫體系

2023-12-04 08:10:34

Spring循環(huán)依賴

2023-10-26 00:37:40

滴滴彈性云公有云

2022-07-11 10:08:34

大數(shù)據(jù)平臺(tái)機(jī)房

2023-02-16 18:22:44

ChatGPTWolfram語言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)