成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

ThreadLocal 為什么會內存泄漏?如何解決?

開發 前端
ThreadLocal是 Java 提供的一種線程封閉機制,每個線程都可以存儲自己的變量副本,互不干擾。那么問題來了:這些變量存儲在哪里呢? 其實,它們存儲在 Thread 里,每個 Thread 內部都有一個 ThreadLocalMap,專門用來存儲 ThreadLocal 變量。

最近,朋友小王在參加某大廠的社招面試,面試官笑瞇瞇地問:“說說ThreadLocal的作用?有啥缺點?”

小王心里一喜,這可是老生常談的問題,于是滔滔不絕地講了一通,啥線程隔離、啥存儲上下文信息、啥用戶Session,統統都擺上了臺面。

面試官聽完點點頭,接著拋出一個靈魂拷問:“那你能分析一下ThreadLocal的內存泄漏問題嗎?以及如何避免?”

小王:“呃……這……ThreadLocal還能內存泄漏?”

完了!涼涼!

回來后,小王苦哈哈地跟我吐槽,我趕緊給他補了一課。今天,我們就一起來探究:ThreadLocal的內存泄漏問題及其解決方案!

ThreadLocal 的底層實現

ThreadLocal是 Java 提供的一種線程封閉機制,每個線程都可以存儲自己的變量副本,互不干擾。那么問題來了:這些變量存儲在哪里呢?

其實,它們存儲在 Thread 里,每個 Thread 內部都有一個 ThreadLocalMap,專門用來存儲 ThreadLocal 變量。

我們來看 Thread 類的源碼(JDK 8):

圖片圖片

嗯,這個 threadLocals 變量就是核心,它的類型是 ThreadLocalMap,專門用來存儲 ThreadLocal 的值。

再看看 ThreadLocalMap 的內部結構(簡化版):

圖片圖片

我們發現了一個關鍵點:Entry 繼承自 WeakReference(弱引用)。這意味著 ThreadLocal 本身是弱引用,但 value 卻是強引用!

那么問題來了!

為什么會內存泄漏?

我們來看這樣一段代碼:

圖片圖片

這段代碼有兩個問題:

  • threadLocal 被置為 null,但 value 依然存在!
  • ThreadLocal 是弱引用,GC 可能會回收它,但 value 依然被 ThreadLocalMap 強引用著!

當 GC 發生時:

  • ThreadLocal 變量本身會被清理掉,因為它是弱引用。
  • ThreadLocalMap 的 Entry.key == null,但 value 還在,占據大量內存!

這樣,如果當前線程是線程池的線程,那么這個 value 就一直不會被回收,導致內存泄漏!

這,就是 ThreadLocal 內存泄漏 的真正原因!

如何避免 ThreadLocal 內存泄漏?

既然知道了原因,那解決方案也就呼之欲出了!

方案 1:手動 remove()

最簡單、最有效的方式,就是在使用完 ThreadLocal 變量后,手動調用 remove() 方法。

圖片圖片

這樣,ThreadLocalMap 里的 Entry 就會被清理掉,value 也就不會泄漏了!

正確示例:

圖片圖片

為什么要用 finally?

因為如果發生異常,導致 remove() 沒有執行,那么 value 還是會泄漏!所以,我們一定要在 finally 代碼塊里手動清理。

方案 2:使用 Static 變量避免多個 ThreadLocal 實例

有時候,我們不希望 ThreadLocal 被 GC 過早回收,可以使用 static 變量 來持有它,確保 ThreadLocal 不會被回收:

圖片圖片

不過,這種方式只適用于 ThreadLocal生命周期和應用一致 的情況,否則可能會導致 ThreadLocal 變量不被回收,反而導致 OOM!

方案 3:使用 InheritableThreadLocal

如果是 子線程需要繼承父線程的 ThreadLocal 變量,可以使用 InheritableThreadLocal,避免子線程訪問不到 ThreadLocal 變量:

圖片圖片

但它不能解決內存泄漏問題,只是拓展了 ThreadLocal 的作用范圍。

總結

常見錯誤

  • 忘記 remove(),導致 value 無法回收。
  • ThreadLocal 被回收,但 value 還在,導致內存泄漏。
  • 線程池使用 ThreadLocal,但不清理,導致長期占用內存。

正確做法

  • 在 finally 代碼塊里手動調用 remove(),避免內存泄漏。
  • 避免不必要的 ThreadLocal 實例,盡量復用。
  • 如果一定要在線程池中使用 ThreadLocal,務必 remove() 掉!

尾聲

小王看完這篇文章,恍然大悟:“原來 ThreadLocal 還有這么大的坑,難怪我面試掛了!”

“那你下次再面試,還怕被問到這個問題嗎?”我笑著問。

“怕啥!我還想主動給面試官講一遍,順便聊聊 JVM 內存模型!”

責任編輯:武曉燕 來源: 軟件求生
相關推薦

2021-08-10 09:58:59

ThreadLocal內存泄漏

2022-05-09 14:09:23

多線程線程安全

2021-03-04 17:21:49

內存檢測泄漏

2022-10-18 08:38:16

內存泄漏線程

2024-10-24 16:51:08

2024-09-29 08:57:25

2023-09-07 17:06:21

@Autowired報錯原因分析

2022-10-25 08:46:26

JSONJavaScript

2018-10-25 15:24:10

ThreadLocal內存泄漏Java

2020-09-10 07:40:28

ThreadLocal內存

2024-09-09 09:41:03

內存溢出golang開發者

2011-05-24 16:39:09

Cfree()

2024-03-22 13:31:00

線程策略線程池

2021-02-18 16:53:44

內存ThreadLocal線程

2024-01-30 10:12:00

Java內存泄漏

2023-04-19 14:20:49

2015-05-15 17:29:13

.Netxp系統如何解決

2016-10-31 20:56:57

Javascript閉包內存泄漏

2023-12-26 17:07:56

GenAICIO

2020-09-24 09:29:34

人工智能
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本黄色免费大片 | 日韩区 | 91精品久久 | 四虎国产 | 久久神马 | 亚洲欧美中文日韩在线v日本 | 国产精品久久久久久久久久不蜜臀 | 精品久久久久久久久久 | 成年人精品视频在线观看 | 成人免费日韩 | 伊色综合久久之综合久久 | 色.com| 美女视频黄色片 | av免费网址 | 亚洲一区二区视频 | 2022精品国偷自产免费观看 | 亚洲一区二区三区四区五区午夜 | 欧美黑人一级爽快片淫片高清 | 日韩av在线一区 | 免费毛片网站在线观看 | 一区天堂 | 午夜精品久久久久久久久久久久 | 午夜不卡福利视频 | 国产成人精品一区二区三区视频 | 九色在线观看 | 午夜精品一区二区三区免费视频 | 久久亚洲一区二区三区四区 | 午夜免费网 | 综合色婷婷 | 一区二区三区四区五区在线视频 | 国产aⅴ | 日本免费网 | av官网在线 | 日韩av福利在线观看 | 国产精品高清在线 | 免费在线精品视频 | h视频免费在线观看 | 欧美久久久久久久久中文字幕 | 91在线精品秘密一区二区 | 欧洲成人 | 91免费在线视频 |