日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sqlserver2008未将对象引用设置到对象的实例_面试官:ThreadLocal 的内存泄漏是弱引用导致的,你确定?...

發布時間:2025/3/20 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sqlserver2008未将对象引用设置到对象的实例_面试官:ThreadLocal 的内存泄漏是弱引用导致的,你确定?... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

面試官:ThreadLocal 了解嗎?

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

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

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

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

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

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

Python 小星:......

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

Python 小星:不太清楚

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


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

看下JDK源碼注釋

翻譯過來:

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

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

ThreadLocal 的基本使用

1、常用方法

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

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

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

3、使用 TL

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

1、JDK 早期設計

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

這么做有一個弊端:

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

2、JDK 1.8 的設計

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

① 每個 Thread 內部都有一個 ThreadLocalMap

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

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

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

好處:

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

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

TL 源碼

1、set 方法

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

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

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

2、get 方法

初始化

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

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

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

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

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

3、remove

4、ThreadLocalMap

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

成員變量

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

Entry

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

弱引用和內存泄漏

1、弱引用相關概念

① java 引用

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

② 強引用和弱引用

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

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

2、內存溢出和內存泄漏

① 內存溢出(memory overflow)

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

② 內存泄漏(memory leak)

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

為什么 TL 里使用弱引用?

首先我們明確 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 使用的線性探測法。

簡單說:

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

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

父子線程如何共享變量?

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

輸出結果:

@Python大星 | 文

總結

以上是生活随笔為你收集整理的sqlserver2008未将对象引用设置到对象的实例_面试官:ThreadLocal 的内存泄漏是弱引用导致的,你确定?...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。