面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

ThreadLocal實際開發有用過嗎? (單選)
0人
0%
A.有
0人
0%
B.沒有
<button>投票/<button>

面試官:ThreadLocal 瞭解嗎?

Python 小星:線程局部變量,多線程下能保證各個線程的變量相對獨立於其他線程的變量。

面試官:那你說下它是如何保證線程隔離的?

Python 小星:每個線程維護一個 ThreadLocalMap ,ThreadLocalMap 和 HashMap 結構類似,key 是 ThreadLocal,通過 hash 算法取餘平均分配到數組上,value 是我們需要的局部變量。有與 key 的唯一性,保證了線程隔離。

面試官:那你說說 ThreadLocalMap 是數組加鏈表的結構解決衝突的嗎?

Python 小星:我的印象裡不是鏈表結構。

面試官:那他是如何解決衝突的?

Python 小星:......

面試官:創建多線程異步執行業務邏輯時,該 ThreadLocal 變量並不能傳遞到子線程中,如何讓父子線程共享變量?

Python 小星:不太清楚

面試官:InheritableThreadLocal 可以下去了解下。今天就先到這,回去等通知吧


什麼是 ThreadLocal?(以下簡稱 TL)

看下JDK源碼註釋

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

翻譯過來:

TL 用來提供線程內部局部變量。這種變量在多線程環境下訪問(通過 get 和 set 方法訪問)時能保證各個線程的變量相對獨立於其他線程的變量。TL 實例通常來說都是 private static 類型,用於關聯線程和線程上下文。


簡單說,ThreadLocal 為每個使用該變量的線程提供獨立的變量副本。所以每個線程都可以獨立地改變自己的副本,而不會影響其他線程所對應的副本,我們通常把這叫“線程隔離”。

ThreadLocal 的基本使用

1、常用方法

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

2、如果不是 TL,會出現什麼問題???

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

輸出結果(多運行幾次):

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

我們可以發現,線程 0 輸出了線程 2 的數據。

3、使用 TL

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

TL 如何實現線程隔離???

1、JDK 早期設計

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

熟悉 hashmap 的老鐵們,比較容易理解:每個 TL 創建一個 Map,然後用線程作為 Map 的 key,要存儲的局部變量作為 Map 的 value,這樣達到線程隔離的目的。

這麼做有一個弊端:

當線程回收時,該線程綁定的變量不能被自動的回收,因為變量存儲在 ThreadLocal 裡,必須顯式的去回收。

2、JDK 1.8 的設計

每個 Thread 維護一個 ThreadLocalMap,這 map 的 key 是 ThreadLocal 實例本身,value 才是真正要存儲的變量值。

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

① 每個 Thread 內部都有一個 ThreadLocalMap

② ThreadLocalMap 裡面存儲 TL 對象(key) 和 線程的變量副本(value)

③ Thread 內部的 ThreadLocalMap 是由 TL 維護的,由 TL 負責向 ThreadLocalMap 設置和獲取變量值

④ 對於不同的線程,每次獲取副本值時,別的線程並不能獲取當前線程的副本值,形成副本的隔離,互不干擾


好處:

① 每個 ThreadLocalMap 存儲的 Entry 數量變少

② 當 Thread 銷燬時,ThreadLocalMap 也隨之銷燬,減少內存的使用

TL 源碼

1、set 方法

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

① 首先獲取當前線程,並根據當前線程獲取一個 map

② 如果獲取的 map 不為空,則將參數設置到 map 中(當前的 TL 的引用設置為 key)

③ 如果 map 為空,則給該線程創建 map ,並設置初始值

2、get 方法

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

初始化

① 獲取當前線程,然後根據當前線程獲取 map

② 如果 map 不為空,則以 TL 的引用為 key 獲取 map 中對應的 Entry e,否則到第 ④ 步

③ 如果 e 不為空,獲取對應的 value 值,否則到第 ④ 步

④ map 為空 或者 e 為空,通過 initialValue ,也就是 NULL,然後用 TL 的引用和 value 作為 firstKey 和 firstValue 創建新的 map

總結:獲取當前線程的 ThreadLocalMap,如果存在則返回值,不存在則創建並返回值。

3、remove

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

4、ThreadLocalMap

ThreadLocalMap 是 TL 的內部類,沒有實現 map 接口。

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

成員變量

從圖中,我們可以發現 SHI 和 HashMap 類似。

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

Entry

Entry 繼承 WeakReference,也就是說 key 是弱引用。

弱引用和內存洩漏

1、弱引用相關概念

① java 引用

4 種類型:強、弱、軟、虛

② 強引用和弱引用

【強引用】:最常見的 new 一個對象,只要強引用指向一個對象,GC 就不會回收

【弱引用】:GC 一旦發現弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存

2、內存溢出和內存洩漏

① 內存溢出(memory overflow)

沒有足夠的內存提供申請者使用。就像一個開水瓶,當你倒水時,如果大於水瓶容量,水就會溢出來。

② 內存洩漏(memory leak)

動態分配的堆內存由於某種原因未釋放或者無法釋放,造成系統內存的浪費,內存洩漏的堆積將造成內存洩漏。

為什麼 TL 裡使用弱引用?

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

首先我們明確 key 是使用了弱引用,當把 threadlocal 實例置為 null 以後,沒有任何強引用指向 threadlocal 實例,所以 threadlocal 就可以順利被 gc 。

我們從圖中也能看到雖然 key 被 gc 回收了,但是 value 還在呀。因為存在一條從 current thread 連接過來的強引用。只有當前 thread 結束以後,current thread 就不會存在棧中,強引用斷開,Current Thread, Map, value 將全部被 GC 回收。

有人會問:無論是強引用還是弱引用,都會出現內存洩漏?用弱引用的好處到底體現在哪?

弱引用會將 key 設置為 null,當使用 map 的 get 和 set 方法時,會判斷 key 是否為 null ,如果為 null,則將 value 設置為 null。弱引用比強引用在 thread 結束之前多一層屏障。

如何解決內存洩漏問題

當線程的某個 localThread 使用完,然後調用 threadlocal 的 remove 方法。


ThreadLocalMap 和 HashMap 的區別?

ThreadLocalMap 和 HashMap 最大的區別在於解決 hash 衝突。

HashMap 使用的拉鍊法,而 ThreadLocalMap 使用的線性探測法。

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

簡單說:

當我們通過 int i = key.threadLocalHashCode & (len-1) 計算出 hash 值,如果出現衝突,順序查看錶中下一單元,直到找出一個空單元或查遍全表。

正因為採取的線性探測法解決衝突,所以在查找的時候,必須比較 key 值是否相等,否則順序尋找下一個單元。

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

父子線程如何共享變量?

使用 InheritableThreadLocal 來解決,底層原理的話各位看官下去看看,下次再續。

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

輸出結果:

面試官:ThreadLocal中的ThreadLocalMap和HashMap有什麼區別?

| 文


分享到:


相關文章: