天天看點

ThreadLocad--概講

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

  1. NEW Threadlocal(); --建立Threadlocal
  2. set 設定目前線程綁定的局部變量
  3. get 擷取目前線程綁定的局部變量
  4. remove() 移除目前線程綁定的變量

哪些地方使用Threadlocal

  1. Spring 事務模闆類
  2. 擷取 HttpRequest
  3. Aop 調用鍊

javaweb項目,tomcat接收請求

建立一個線程接受請求—aop目标方法

  1. 設計模式 模闆方法—
  2. 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​​

  1. 在每個線程中都有自己獨立的ThreadlocalMap對象,中Entry對象
  2. 如果在目前線程對應的ThreadlocalMap對象為空的情況下,則建立ThreadlocalMap對象,并且指派鍵值對

key為目前的new Threadlocal 對象 value就是object變量值

ThreadLocad--概講

為什麼線程緩存的是 ThreadlocalMap 對象

Threadlocal可以存放n多個不同的Threadlocal對象

每個Threadlocal對象隻能緩存一個變量值

ThreadLocalMap <ThreadLocal 對象,value> threadLocalMap

ThreadLocal.get();

threadLocalMap.get(ThreadLocal)-----緩存變量值

談談強、軟、弱、虛引用 差別

強引用: 當記憶體不足時,JVM 開始進行 GC(垃圾回收),對于強引用對象,就算是出現了 OOM 也不會對該對象進行回收,死都不會收。

軟引用:當系統記憶體充足的時候,不會被回收;當系統記憶體不足時,它會被回收,軟引用通 常用在對記憶體敏感的 程式中,比如高速緩存就用到軟引用,記憶體夠用時就保留,不夠時就 回收

ThreadLocad--概講
ThreadLocad--概講

弱引用:弱引用需要用到​

​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如果沒有清理垃圾時,則該對象一直無法被垃圾機制回收,一直占用到了系統記憶體,有可能會發生記憶體洩漏的問題。

ThreadLocad--概講

如何防禦 Threadlocal 記憶體洩漏問題

  1. 自己調用remove方法将不要的資料移除避免記憶體洩漏的問題
  2. 每次在做set方法的時候 清除之前的key為NULL
  3. 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

ThreadLocad--概講