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

ThreadLocal工作原理及用法案例

 更新時間:2021年12月25日 10:00:25   作者:卡斯特梅的雨傘  
本文詳細講解了ThreadLocal工作原理及用法案例,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

ThreadLocal是什么

ThreadLocal是線程Thread中屬性threadLocals即ThreadLocal.ThreadLocalMap的管理者,ThreadLocal用于給每個線程操作自己線程的本地變量,通過線程私有從而保證線程安全性。

ThreadLocal原理

get()方法來說,線程的本地變量是存放在線程實例的屬性ThreadLocalMap上的,ThreadLocalMap本質(zhì)上就是一個HashMap,ThreadLocal只是一個管理者,當我們的線程需要拿到自己的本地變量時,我們直接調(diào)用ThreadLocal去get本地變量即可。
因為get()方法底層會先獲取到當前線程,然后通過當前線程拿到他的屬性值ThreadLocalMap,如果ThreadLocalMap為空,則會調(diào)用ThreadLocal的初始化方法拿到初始值返回,如果不為空,則會拿該ThreadLocal作為key去獲取該線程下的ThreadLocalMap里對應(yīng)的value值。

ThreadLocal內(nèi)存泄漏問題

線程的屬性值ThreadLocalMap中使用的 key 為 ThreadLocal 的弱引用,而value是強引用。所以,如果ThreadLocal沒有被外部強引用的情況下,在垃圾回收的時候,key 會被清理掉,而value 不會被清理掉。這樣的話,ThreadLocalMap 中就會出現(xiàn) key 為 null 的 Entry。假如我們不做任何措施的話,value 永遠無法被 GC 回收,這個時候就可能會產(chǎn)生內(nèi)存泄露。
因此針對這種情況,我們有兩種原則:

  • ThreadLocal申明為private static final。JDK建議ThreadLocal定義為private static,這樣ThreadLocal的弱引用問題則不存在了。
    • private與final 盡可能不讓他人修改變更引用。
    • static 表示為類屬性,只有在程序結(jié)束才會被回收。
  • ThreadLocal使用后務(wù)必調(diào)用remove方法。
    • 最簡單有效的方法是使用后將其移除。

關(guān)于InheritableThreadLocal

InheritableThreadLocal類是ThreadLocal類的子類。ThreadLocal中每個線程擁有它自己的值,與ThreadLocal不同的是,InheritableThreadLocal允許一個線程以及該線程創(chuàng)建的所有子線程都可以訪問它保存的值。

代碼示例

ThreadLocal使用

public class ThreadLocalTest {

    //第一種初始化方式
    /**
     * 聲明為static是讓ThreadLocal實例隨著程序的結(jié)束才結(jié)束,這樣才不會讓GC回收了
     * 聲明為final是讓ThreadLocal實例引用不會被替換,這樣子也不會因為被替換導(dǎo)致被GC回收
     * 這兩個聲明都是為了避免作為key的ThreadLocal對象沒有外部強引用而導(dǎo)致被GC回收,從而導(dǎo)致內(nèi)存泄漏的問題,因為ThreadLocalMap<ThreadLocal, Object>中的ThreadLocal
     * 對象作為key是弱引用,會被GC回收。
     */
    private static final ThreadLocal<String> threadLocalStr = ThreadLocal.withInitial(() -> "fresh");

    private static AtomicInteger intGen = new AtomicInteger(0);
    //第二種初始化方式
    private static final ThreadLocal<Integer> threadLocalInt = new ThreadLocal<Integer>() {
        @Override
        public Integer initialValue() {
            return intGen.incrementAndGet();
        }
    };

    public static void main(String[] args) throws InterruptedException {
        ArrayList<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            Thread t = new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "   " + threadLocalInt.get());
                    System.out.println(Thread.currentThread().getName() + "   " + threadLocalStr.get());
                    TimeUnit.SECONDS.sleep(5);
                    threadLocalStr.set("bojack horseman" + threadLocalInt.get());
                    System.out.println(Thread.currentThread().getName() + "   " + threadLocalInt.get());
                    System.out.println(Thread.currentThread().getName() + "   " + threadLocalStr.get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    threadLocalInt.remove();
                    threadLocalStr.remove();
                }
            });
            t.start();
            threads.add(t);
        }
        TimeUnit.SECONDS.sleep(2);
        System.out.println(threads);
        System.out.println(threadLocalStr);
        System.out.println(threadLocalInt);
    }
    /**
     * Thread-0   1
     * Thread-1   2
     * Thread-0   fresh
     * Thread-1   fresh
     * [Thread[Thread-0,5,main], Thread[Thread-1,5,main]]
     * java.lang.ThreadLocal$SuppliedThreadLocal@1ef7fe8e
     * cn.vv.schedule.test.ThreadLocalTest$1@6f79caec
     * Thread-1   2
     * Thread-1   bojack horseman2
     * Thread-0   1
     * Thread-0   bojack horseman1
     */

}

InheritableThreadLocal使用

public class InheritableThreadLocalTest {

    //第一種初始化方式
    private static final InheritableThreadLocal<String> threadLocalStr = new InheritableThreadLocal<String>() {
        @Override
        public String initialValue() {
            return "fresh";
        }
    };
    private static AtomicInteger intGen = new AtomicInteger(0);
    //第二種初始化方式
    private static final ThreadLocal<Integer> threadLocalInt = new ThreadLocal<Integer>() {
        @Override
        public Integer initialValue() {
            return intGen.incrementAndGet();
        }
    };

    public static void main(String[] args) throws InterruptedException {
        //如果是InheritableThreadLocal,則父線程創(chuàng)建的所有子線程都會復(fù)制一份父線程的線程變量,而不是去初始化一份線程變量
        threadLocalStr.set("main");
        ArrayList<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            Thread t = new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "   " + threadLocalInt.get());
                    System.out.println(Thread.currentThread().getName() + "   " + threadLocalStr.get());
                    TimeUnit.SECONDS.sleep(5);
                    //子線程可以自由地改變自己的本地變量
                    threadLocalStr.set("bojack horseman" + threadLocalInt.get());
                    System.out.println(Thread.currentThread().getName() + "   " + threadLocalInt.get());
                    System.out.println(Thread.currentThread().getName() + "   " + threadLocalStr.get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    threadLocalInt.remove();
                    threadLocalStr.remove();
                }
            });
            t.start();
            threads.add(t);
        }
        TimeUnit.SECONDS.sleep(2);
        System.out.println(Thread.currentThread().getName() + "   " + threadLocalStr.get());
    }
    /**
     * Thread-0   2
     * Thread-1   1
     * Thread-0   main
     * Thread-1   main
     * main   main
     * Thread-0   2
     * Thread-0   bojack horseman2
     * Thread-1   1
     * Thread-1   bojack horseman1
     */

}

參考

ThreadLocal理解及應(yīng)用

相關(guān)文章

  • 你都理解創(chuàng)建線程池的參數(shù)嗎?

    你都理解創(chuàng)建線程池的參數(shù)嗎?

    這篇文章主要介紹了創(chuàng)建線程池參數(shù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • SpringBoot實現(xiàn)WebSocket的示例代碼

    SpringBoot實現(xiàn)WebSocket的示例代碼

    這篇文章主要為大家詳細介紹了SpringBoot實現(xiàn)WebSocket的相關(guān)知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • java開發(fā)微服務(wù)架構(gòu)設(shè)計消息隊列的水有多深

    java開發(fā)微服務(wù)架構(gòu)設(shè)計消息隊列的水有多深

    今天我們說說消息隊列的問題,來帶大家探一探消息隊列的水有多深,希望看完本文大家在引入消息隊列的時候先想一想,是不是一定要引入?引入消息隊列后產(chǎn)生的問題能不能解決
    2021-10-10
  • springboot集成shiro權(quán)限管理簡單實現(xiàn)

    springboot集成shiro權(quán)限管理簡單實現(xiàn)

    這篇文章主要介紹了springboot集成shiro權(quán)限管理簡單實現(xiàn),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Java與C++分別用遞歸實現(xiàn)漢諾塔詳解

    Java與C++分別用遞歸實現(xiàn)漢諾塔詳解

    漢諾塔問題是一個經(jīng)典的問題。漢諾塔(Hanoi Tower),又稱河內(nèi)塔,源于印度一個古老傳說。本文將用Java與C++分別實現(xiàn),感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • springboot多租戶設(shè)計過程圖解

    springboot多租戶設(shè)計過程圖解

    這篇文章主要介紹了springboot多租戶設(shè)計過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • Spring循環(huán)依賴之問題復(fù)現(xiàn)詳解

    Spring循環(huán)依賴之問題復(fù)現(xiàn)詳解

    這篇文章主要為大家詳細介紹了Spring的循環(huán)依賴什么時候會出現(xiàn)以及如何解決循環(huán)依賴,文中的示例代碼講解詳細,感興趣的可以學(xué)習(xí)一下
    2022-07-07
  • Spring MVC處理方法返回值過程解析

    Spring MVC處理方法返回值過程解析

    這篇文章主要介紹了Spring MVC處理方法返回值過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • springboot使用注解獲取yml配置的兩種方法

    springboot使用注解獲取yml配置的兩種方法

    本文主要介紹了springboot使用注解獲取yml配置的兩種方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • Spring Boot中的那些條件判斷的實現(xiàn)方法

    Spring Boot中的那些條件判斷的實現(xiàn)方法

    這篇文章主要介紹了Spring Boot中的那些條件判斷的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評論

伊金霍洛旗| 崇礼县| 临沧市| 平定县| 长海县| 伊宁市| 灯塔市| 白水县| 固阳县| 玉环县| 边坝县| 滨海县| 溆浦县| 新竹县| 航空| 广德县| 新建县| 英吉沙县| 马边| 合肥市| 延庆县| 抚顺市| 保靖县| 湘潭县| 汉中市| 绍兴市| 奉化市| 大庆市| 甘洛县| 遵义县| 刚察县| 嵊州市| 屏东市| 广宗县| 安图县| 嵊泗县| 咸丰县| 搜索| 綦江县| 永川市| 东源县|