欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java并發(fā)編程之threadLocal

 更新時間:2021年09月29日 08:51:59   作者:黑夜中的小迷途  
ThreadLocal是JDK包提供的,它提供了線程本地變量,也就是說如果創(chuàng)建了一個ThreadLocal變量,需要的朋友可以參考一下喲

1、ThreadLocal介紹

多個線程訪問同一個共享變量時特別容易出現(xiàn)并發(fā)問題,特別是多線程需要對共享變量進行寫入時。為了保證線程安全,一般使用者在訪問共享變量的時候需要進行適當?shù)耐?,如圖

同步的一般措施是加鎖,這就需要使用者對鎖有一定的了解,這顯然加重了使用者的負擔,那么有沒有一種方法可以做到,當創(chuàng)建一個變量后,每個線程對其進行訪問的時候訪問的是自己線程的變量呢?其實ThreadLocal就可以做到。

ThreadLocalJDK包提供的,它提供了線程本地變量,也就是說如果創(chuàng)建了一個ThreadLocal變量,那么訪問這個變量的每一個線程都會有這個變量的一個本地副本。當多線程操作這個變量的時候,實際操作的就是自己本地內(nèi)存的里面的里面的變量,從而避免了線程安全問題。創(chuàng)建一個ThreadLocal變量后,每一個線程都會復制一個變量到自己的本地內(nèi)存。

2、ThreadLocal使用實例

package com.heiye.learn1;

public class ThreadLocalTest {
    //print方法
    static void print(String threadName) {
        //打印當前線程本地內(nèi)存中LocalVariable變量的值
        System.out.println(threadName + ":" + localVariable.get());
        //清除當前線程本地內(nèi)存中的localVariable變量值
        //localVariable.remove();
    }

    //創(chuàng)建ThreadLocal變量
    static ThreadLocal<String> localVariable = new ThreadLocal<>();

    public static void main(String[] args) {
        //創(chuàng)建線程threadOne
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                //設(shè)置線程one變量localVariable值
                localVariable.set("threadOne local Variable");
                //調(diào)用打印函數(shù)
                print("threadOne");
                //打印本地變量值
                System.out.println("threadOne remove after" + ":" + localVariable.get());
            }
        });
        //創(chuàng)建線程threadTwo
        Thread threadTwo = new Thread(new Runnable() {
            @Override
            public void run() {
                //設(shè)置線程two變量localVariable值
                localVariable.set("threadTwo local Variable");
                //調(diào)用打印函數(shù)
                print("threadTwo");
                //打印本地變量值
                System.out.println("threadTwo remove after" + ":" + localVariable.get());
            }
        });

        threadOne.start();
        threadTwo.start();
    }
}

線程one首先通過set()方法為threadLocal變量設(shè)置了一個值,這其實設(shè)置的就是線程one本地內(nèi)存中對于threadLocal變量的一個副本。這個副本是線程two訪問不了的。

如果清除當前線程本地內(nèi)存中的localVariable變量值,也就是執(zhí)行localVariable.remove() ;則:

3、ThreadLocal實現(xiàn)原理

首先查看一下ThreadLocal類圖結(jié)構(gòu)

由該圖可知,Thread類有一個ThreadLocalsinheritableThreadLocals,它們都是ThreadLocalMap類型的變量,而ThreadLocalMap是一個定制化的HashMap。在默認的情況下,每個線程中的兩個變量都為null,只有當?shù)谝粋€線程調(diào)用ThreadLocal的set或者get方法時才會創(chuàng)建它們,其實每個線程得到本地變量不是存放在ThreadLocal實例里面,而是存放在具體的線程內(nèi)存空間里。ThreadLocal就是一個工具殼,它通過set方法把value值存放在調(diào)用線程的threadlocals里面并存放起來,當調(diào)用線程調(diào)用它的get()方法的時候,再從當前線程的threadLocals變量里面將其拿出來使用。

分析setget,remove邏輯

 //set
 public void set(T value) {
        //獲取當前線程
        Thread t = Thread.currentThread();
        //將當前線程作為key,到ThreadLocalMap取查找對應(yīng)的線程變量
        ThreadLocalMap map = getMap(t);
        //如果找到,則設(shè)置
        if (map != null)
            map.set(this, value);
        else //第一次調(diào)用就創(chuàng)建當前線程所在的hashmap
            createMap(t, value);
    }

 //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();
    }

 //remove
 public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

在每一個線程內(nèi)都有一個名為threadLocals的成員變量,該變量的類型為HashMap,其中的key為我們定義的threadLocal變量的this引用,value為我們使用set方法設(shè)置的值。每個線程的本地變量存放在自己的內(nèi)存變量ThreadLocals中,如果當前線程一直不消亡,那么這些本地變量會一直存在,所有可能造成內(nèi)存溢出。

到此這篇關(guān)于Java并發(fā)編程 threadLocal 的文章就介紹到這了,更多相關(guān)threadLocal 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文帶你入門SpringMVC的配置與使用

    一文帶你入門SpringMVC的配置與使用

    Spring MVC是Spring Framework的一部分,是基于Java實現(xiàn)MVC的輕量級Web框架。本文將通過一些簡單示例帶大家掌握SpringMVC的配置與使用,感興趣的可以了解一下
    2022-11-11
  • Java實現(xiàn)帶頭結(jié)點的單鏈表

    Java實現(xiàn)帶頭結(jié)點的單鏈表

    這篇文章主要為大家詳細介紹了Java實現(xiàn)帶頭結(jié)點的單鏈表,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • Spring rest接口中的LocalDateTime日期類型轉(zhuǎn)時間戳

    Spring rest接口中的LocalDateTime日期類型轉(zhuǎn)時間戳

    這篇文章主要介紹了Spring rest接口中的LocalDateTime日期類型轉(zhuǎn)時間戳的方法,Java程序中一般將日期類型定義為LocalDateTime,數(shù)據(jù)庫中保存的時間是0時區(qū)的時間
    2023-03-03
  • 如何在Java中使用標準庫創(chuàng)建臨時文件

    如何在Java中使用標準庫創(chuàng)建臨時文件

    有時候我們程序運行時需要產(chǎn)生中間文件,但是這些文件只是臨時用途,并不做長久保存,我們可以使用臨時文件,不需要長久保存,這篇文章主要給大家介紹了關(guān)于如何在Java中使用標準庫創(chuàng)建臨時文件的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • springboot結(jié)合mysql主從來實現(xiàn)讀寫分離的方法示例

    springboot結(jié)合mysql主從來實現(xiàn)讀寫分離的方法示例

    這篇文章主要介紹了springboot結(jié)合mysql主從來實現(xiàn)讀寫分離的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • springboot后端如何實現(xiàn)攜帶token登陸

    springboot后端如何實現(xiàn)攜帶token登陸

    這篇文章主要介紹了springboot后端如何實現(xiàn)攜帶token登陸,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Spring Boot2.0中SpringWebContext找不到無法使用的解決方法

    Spring Boot2.0中SpringWebContext找不到無法使用的解決方法

    這篇文章主要給大家介紹了關(guān)于Spring Boot2.0中SpringWebContext找不到無法使用的解決方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧
    2018-12-12
  • Java使用黑盒方式模擬實現(xiàn)內(nèi)網(wǎng)穿透

    Java使用黑盒方式模擬實現(xiàn)內(nèi)網(wǎng)穿透

    這篇文章主要介紹了Java使用黑盒方式模擬實現(xiàn)內(nèi)網(wǎng)穿透,內(nèi)網(wǎng)穿透,也即 NAT 穿透,進行 NAT 穿透是為了使具有某一個特定源 IP 地址和源端口號的數(shù)據(jù)包不被 NAT 設(shè)備屏蔽而正確路由到內(nèi)網(wǎng)主機,需要的朋友可以參考下
    2023-05-05
  • Java全面細致講解Wrapper的使用

    Java全面細致講解Wrapper的使用

    在封裝中有一種特殊的類,能夠把基本的數(shù)據(jù)類型進行轉(zhuǎn)換來方便實際的使用。我們在之前提到的一些數(shù)據(jù)類型,最明顯的特征是所有字母為小寫狀態(tài),那么經(jīng)過Wrapper的包裝后,首字母就變成了大寫。下面我們就這種特殊的封裝類Wrapper的使用
    2022-05-05
  • SpringCloud maven-assembly-plugin 多級目錄打包的實現(xiàn)

    SpringCloud maven-assembly-plugin 多級目錄打包的實現(xiàn)

    本文主要介紹了SpringCloud maven-assembly-plugin 多級目錄打包的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10

最新評論