ThreadLocad
底層實作原理1
底層實作原理2
ThreadLocal#ThreadLocalMap内部類實作細節
文章目錄
- ThreadLocad
- 底層實作原理1
- 底層實作原理2
- ThreadLocal#ThreadLocalMap内部類實作細節
- Threadlocal基本API
- 哪些地方使用Threadlocal
- Threadlocal 底層實作原理
- 底層實作原理1
- 底層實作原理2
- 為什麼線程緩存的是 ThreadlocalMap 對象
- 談談強、軟、弱、虛引用 差別
- Threadlocal 為何引發記憶體洩漏問題
- 如何防禦 Threadlocal 記憶體洩漏問題
- Threadlocal 采用弱引用而不是強引用
Threadlocal提供了線程本地變量,它可以保證通路到的變量屬于目前線程,每個線程都儲存了一個變量的副本,每個線程的變量不同,Threadlocal相當于提供了一種線程隔離,将變量與線程綁定
Threadlocal适用于在多線程的情況下,可以實作傳遞資料,實作資料隔離
Threadlocal提供給我們每個線程緩存局部變量
Threadlocal基本API
- NEW Threadlocal(); --建立Threadlocal
- set 設定目前線程綁定的局部變量
- get 擷取目前線程綁定的局部變量
- remove() 移除目前線程綁定的變量
哪些地方使用Threadlocal
- Spring 事務模闆類
- 擷取 HttpRequest
- Aop 調用鍊
javaweb項目,tomcat接收請求
建立一個線程接受請求—aop目标方法
- 設計模式 模闆方法—
- SpringMVC 擷取HttpRequest 對象+==SPringMVC封裝 将HttpRequest 對象緩存在目前線程中
javaweb中的SpringMVC
- tomcat接受請求.建立一個線程
- servlet架構處理請求
- SpringMVC servlet 做了一層封裝,封裝HttpRequest 對象放入目前的Threadlocal
- AOP攔截請求
-
控制層—Threadlocal擷取到HttpRequest
最終都是同一個線程子啊處理,(中間經過n多個不同的方法)
AOP攔截器請求–AOP 緩存一個變量Threadlocal中
–控制層擷取到該變量
分層架構
控制層 --将變量緩存到Threadlocal中
業務邏輯層 — 從Threadlocal 擷取到該變量
DB層
Threadlocal 底層實作原理
底層實作原理1
底層實作原理2
- 在每個線程中都有自己獨立的ThreadlocalMap對象,中Entry對象
- 如果在目前線程對應的ThreadlocalMap對象為空的情況下,則建立ThreadlocalMap對象,并且指派鍵值對
key為目前的new Threadlocal 對象 value就是object變量值
為什麼線程緩存的是 ThreadlocalMap 對象
Threadlocal可以存放n多個不同的Threadlocal對象
每個Threadlocal對象隻能緩存一個變量值
ThreadLocalMap <ThreadLocal 對象,value> threadLocalMap
ThreadLocal.get();
threadLocalMap.get(ThreadLocal)-----緩存變量值
談談強、軟、弱、虛引用 差別
強引用: 當記憶體不足時,JVM 開始進行 GC(垃圾回收),對于強引用對象,就算是出現了 OOM 也不會對該對象進行回收,死都不會收。
軟引用:當系統記憶體充足的時候,不會被回收;當系統記憶體不足時,它會被回收,軟引用通 常用在對記憶體敏感的 程式中,比如高速緩存就用到軟引用,記憶體夠用時就保留,不夠時就 回收
弱引用:弱引用需要用到
java.lang.ref.WeakReference
類來實作,它比軟引用的生存周期更短。 對于隻有弱引用的對象來說,隻要有垃圾回收,不管 JVM 的記憶體空間夠不夠用,都會回收 該對象占用的記憶體空間。
System.gc() 可以清理弱引用
虛:虛引用需要
java.lang.ref.Phantomreference
類來實作。顧名思義,虛引用就是形同虛設。 與其它幾種引用不同,虛引用并不會決定對象的聲明周期。
Threadlocal 為何引發記憶體洩漏問題
補充概念: 什麼是記憶體洩漏問題
記憶體洩漏: 表示就是我們程式員申請了記憶體,但是該記憶體一直無法釋放
記憶體洩漏溢出問題:
申請記憶體時,發現申請記憶體不足,就會報錯,記憶體溢出的問題
因為每個線程中都有自己獨立的
ThreadLocalMap
對象,key為
ThreadLocal
,
value
是為變量值
key為ThreadLocal 最為Entry對象key,為弱引用,當ThreadLocal指向null的時候,Entry對象中的key變為null…GC如果沒有清理垃圾時,則該對象一直無法被垃圾機制回收,一直占用到了系統記憶體,有可能會發生記憶體洩漏的問題。
如何防禦 Threadlocal 記憶體洩漏問題
- 自己調用remove方法将不要的資料移除避免記憶體洩漏的問題
- 每次在做set方法的時候 清除之前的key為NULL
- Threadlocal為弱引用
Threadlocal 采用弱引用而不是強引用
1.如果 key 是為強引用: 當我們現在将 ThreadLocal 的引用指向為 null,但是 每個線程中有自己獨立 ThreadLocalMap 還一直在繼續持有該對象,但是我們 ThreadLocal 對象不會被回收,就會發生 ThreadLocal 記憶體洩漏的問題。
2.如果 key 是為弱引用: 當我們現在将 ThreadLocal 的引用指向為 null,Entry 中的 key 指向為 null,但是 下次調用 set 方法的時候,會根據判斷如果 key 空的情況下,直接删除,避免了 Entry 發生 記憶體洩漏的問題。
3.不管是用強引用還是弱引用都是會發生記憶體洩漏的問題。 弱引用中不會發生 ThreadLocal 記憶體洩漏的問題。
4.但是最終根本的原因 Threadlocal 記憶體洩漏的問題,産生于 ThreadLocalMap 與 我們目前線程的生命周期一樣,如果沒有手動的删除的情況下,就有可能會發生記憶體洩漏的 問題。
(強制)在代碼邏輯中使用完Threadlocal,都要調用remove方法,及時清理
(推薦)盡量不要使用全局的Threadlocal