最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

告訴你為什么?ThreadLocal?可以做到線程隔離

 更新時間:2022年07月26日 09:05:19   作者:劉水鏡  
對于 ThreadLocal 我們都不陌生,它的作用如同它的名字用于存放線程本地變量,這篇文章主要介紹了為什么?ThreadLocal?可以做到線程隔離,需要的朋友可以參考下

對于 ThreadLocal 我們都不陌生,它的作用如同它的名字——用于存放「線程本地」變量。

先通過一個小例子感受一下:

private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) throws Throwable {
    Thread threadOne = new Thread(()->{
        threadLocal.set("ThreadOne:" + Thread.currentThread().getName());
        log.info("線程 One 本地變量值為:{}", threadLocal.get());
        threadLocal.remove();
        log.info("線程 One remove 后本地變量值為:{}", threadLocal.get());
    });
    Thread threadTwo = new Thread(()->{
        threadLocal.set("ThreadTwo:" + Thread.currentThread().getName());
        log.info("線程 Two 本地變量值為:{}", threadLocal.get());
    });
    threadOne.start();
    threadTwo.start();
}

運行結果:

線程 One 本地變量值為:ThreadOne:Thread-0
線程 One remove 后本地變量值為:null
線程 Two 本地變量值為:ThreadTwo:Thread-1

OK,從效果上看,ThreadLocal 確實是線程隔離的,那么,它是如何做到線程隔離的呢?下面我們扒一扒源碼,看看它是如何做到的:

public void set(T value) {
   Thread t = Thread.currentThread();
   ThreadLocalMap map = getMap(t);
   if (map != null)
       map.set(this, value);
   else
       createMap(t, value);
}

set() 方法的邏輯如下:

  • 獲取當前線程
  • 根據(jù)當前線程獲取一個 ThreadLocalMap 對象
  • 如果 map 不為 null 則保存
  • 如果 map 為 null 則創(chuàng)建一個 map

getMap() 和 createMap() 方法都干了啥呢?我們點進去看:

ThreadLocalMap getMap(Thread t) {
   return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
   t.threadLocals = new ThreadLocalMap(this, firstValue);
}

進入到兩個方法內部后發(fā)現(xiàn),不管執(zhí)行哪個分支,最終是把值保存到了當前線程的 threadLocals 屬性中。

查看 Thread 類的源碼,你會發(fā)現(xiàn)類中定義了一個 threadLocals 屬性,且初始值為 null,其類型為ThreadLocal.ThreadLocalMap。

public class Thread implements Runnable {
// ...
   ThreadLocal.ThreadLocalMap threadLocals = null;
// ...
}

到此,我們發(fā)現(xiàn)了,原來 ThreadLocal 就是把我們要傳遞的對象放到了當前線程的 threadLocals 屬性中。也就是說每個線程在用 ThreadLocal 保存對象時,其實就是將對象放到了當前線程實例對象的 threadLocals 屬性里面。這樣一來線程之間自然就是互相獨立的啦。

再看看 get() 方法:

public T get() {
   Thread t = Thread.currentThread();
   ThreadLocalMap map = getMap(t);
   if (map != null) {
       ThreadLocalMap.Entry e = map.getEntry(this);
       if (e != null) {
           @SuppressWarnings("unchecked")
           T result = (T)e.value;
           return result;
      }
  }
   return setInitialValue();
}

private T setInitialValue() {
   T value = initialValue();
   Thread t = Thread.currentThread();
   ThreadLocalMap map = getMap(t);
   if (map != null)
       map.set(this, value);
   else
       createMap(t, value);
   return value;
}

ThreadLocal 的 get() 方法其實和 set() 方法邏輯很相似,先從當前線程的 threadLocals 屬性中取,如果該屬性為 null,那么就初始化。

當線程結束時,會調用當前線程實例的 exit() 方法,將 threadLocals 設置為 null,以便垃圾回收器將其回收掉。

// THread 類中的方法
private void exit() {
   // ...
   threadLocals = null;
   // ...
}

最后,有一點需要格外注意:用完 ThreadLocal 一定要記得手動調用 remove() 方法,否則可能會產(chǎn)生臟數(shù)據(jù)甚至產(chǎn)生內存泄漏。

為啥呢?上面不是說線程結束時,會將 threadLocals 置為 null 嗎?

是的,線程結束時,確實會做清理工作。

但,如果線程一直不結束呢?如果線程會被復用呢?比如使用了線程池。

所以,使用 ThreadLocal 一定要手動 remove()。?

補充:下面看下ThreadLocal 是什么?有哪些使用場景?

ThreadLocal是一個本地線程副本變量工具類,主要用于將私有線程和該線程存放的副本對象做一個映射,各個線程之間的變量互不干擾。

說人話就是,ThreadLocal在每個線程都創(chuàng)建副本,每個線程可以訪問自己的副本,線程之間相互不影響。

使用場景:

多線程環(huán)境中為每一個jdbc分配一個Connection連接,使用ThreadLocal去保存連接,這樣就保證了每個線程在自己的連接上操作數(shù)據(jù)庫,不會出現(xiàn)A線程關閉B的Connnection操作

Web中的session管理時,可以使用ThreadLocal記錄每個線程的Session,這樣保證每個線程都可以獲取自己的session

解決線程安全問題,對于需要進行線程隔離的變量,可以使用ThreadLocal存儲,確保線程隔離

總結:

ThreadLocal可以簡單看作一個map,每個線程保存一個map,這個map只能存儲一組數(shù)據(jù),key為線程id, value就是要存的值

一個ThreadLocal只能存儲一個變量,如果要存多個就創(chuàng)建多個ThreadLocal對象。

到此這篇關于為什么 ThreadLocal 可以做到線程隔離?的文章就介紹到這了,更多相關ThreadLocal 線程隔離內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • MyBatis-Plus如何解決主鍵自增問題

    MyBatis-Plus如何解決主鍵自增問題

    這篇文章主要介紹了MyBatis-Plus如何解決主鍵自增問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • window?下?win10?jdk8安裝與環(huán)境變量的配置過程

    window?下?win10?jdk8安裝與環(huán)境變量的配置過程

    這篇文章主要介紹了window?下?win10?jdk8安裝與環(huán)境變量的配置,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • Java中嵌入式MySQL的使用方法

    Java中嵌入式MySQL的使用方法

    這篇文章主要為大家詳細介紹了Java中嵌入式MySQL的使用方法,Java中如何使用嵌入MySQL,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 構建Maven多模塊項目的方法

    構建Maven多模塊項目的方法

    這篇文章主要介紹了構建Maven多模塊項目的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • SpringSecurity實現(xiàn)訪問控制url匹配

    SpringSecurity實現(xiàn)訪問控制url匹配

    本文主要介紹了SpringSecurity實現(xiàn)訪問控制url匹配,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • 解決idea中servlet報紅問題

    解決idea中servlet報紅問題

    這篇文章主要介紹了解決idea中servlet報紅問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • java基礎javeSE程序邏輯控制語法

    java基礎javeSE程序邏輯控制語法

    主要講解Java中程序的邏輯控制語句包括 Java中的輸入輸出方式 順序結構循環(huán)結構等,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-09-09
  • spring?cloud之eureka高可用集群和服務分區(qū)解析

    spring?cloud之eureka高可用集群和服務分區(qū)解析

    這篇文章主要介紹了spring?cloud之eureka高可用集群和服務分區(qū)解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Spring框架基于注解的AOP之各種通知的使用與環(huán)繞通知實現(xiàn)詳解

    Spring框架基于注解的AOP之各種通知的使用與環(huán)繞通知實現(xiàn)詳解

    這篇文章主要介紹了Spring框架基于注解的AOP之各種通知的使用及其環(huán)繞通知,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-11-11
  • Sentinel熱點規(guī)則示例詳解分析

    Sentinel熱點規(guī)則示例詳解分析

    這篇文章主要介紹了何為熱點?熱點即經(jīng)常訪問的數(shù)據(jù)。很多時候我們希望統(tǒng)計某個熱點數(shù)據(jù)中訪問頻次最高的 Top K 數(shù)據(jù),并對其訪問進行限制
    2021-09-09

最新評論

颍上县| 岳阳市| 彩票| 鄂伦春自治旗| 博白县| 土默特右旗| 汉沽区| 松江区| 佛坪县| 隆回县| 攀枝花市| 固始县| 赣榆县| 营山县| 株洲县| 刚察县| 海宁市| 海南省| 临沧市| 朝阳县| 巴林左旗| 博罗县| 泸水县| 呼伦贝尔市| 黄平县| 柯坪县| 普宁市| 云阳县| 安乡县| 张家港市| 兴文县| 响水县| 五台县| 玛纳斯县| 嘉兴市| 高平市| 大埔区| 峡江县| 上饶县| 刚察县| 弋阳县|