AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

ThreadLocal和InheritableThreadLocal詳解

來源: 責編: 時間:2023-10-08 07:05:54 289觀看
導讀一、概述為了方便且更加安全的進行多線程編程,jdk引入ThreadLocal和InheritableThreadLocal兩個類,以供開發人員進行多線程之間的數據傳遞和數據共享。InheritableThreadLocal是ThreadLocal的子類,它可以實現子線程共享

7HP28資訊網——每日最新資訊28at.com

一、概述

為了方便且更加安全的進行多線程編程,jdk引入ThreadLocal和InheritableThreadLocal兩個類,以供開發人員進行多線程之間的數據傳遞和數據共享。InheritableThreadLocal是ThreadLocal的子類,它可以實現子線程共享父線程的變量。7HP28資訊網——每日最新資訊28at.com

二、案例介紹

ThreadLocal:7HP28資訊網——每日最新資訊28at.com

private static ThreadLocal<String> testThreadLocal = new ThreadLocal<>();/*// 創建時可重寫初始化方法ThreadLocal<String> testThreadLocal = new ThreadLocal<String>(){    public Connection initialValue(){        return "zhangsan";    }};*/public static void main(String[] args) {        // 設置線程變量        testThreadLocal.set("zhangsan");        // 獲取線程變量        String userName = testThreadLocal.get();        System.out.println("userName: " + userName);        // 刪除線程變量        testThreadLocal.remove();        userName = testThreadLocal.get();        System.out.println("userName: " + userName);}#結果輸出userName: zhangsanuserName: null
public static void main(String[] args) {        // 主線程        testThreadLocal.set("zhangsan");        System.out.println("userName0: " + testThreadLocal.get());        // 線程1        new Thread(() -> {            testThreadLocal.set("lisi");            System.out.println("userName1: " + testThreadLocal.get());        }).start();        // 線程2        new Thread(() -> {            testThreadLocal.set("wangwu");            System.out.println("userName2: " + testThreadLocal.get());        }).start();}#結果輸出【線程之間變量相關隔離】userName0: zhangsanuserName1: lisiuserName2: wangwu

接下來看下set方法:7HP28資訊網——每日最新資訊28at.com

public void set(T value) {    // 獲取當前線程(調用方線程:主線程、線程1......)    Thread t = Thread.currentThread();    // 當前線程作為key,獲取對應的線程變量ThreadLocalMap    ThreadLocalMap map = getMap(t);    if (map != null) {        // 設置線程變量:key為當前定義的ThreadLocal實例的this引用,值為我們傳入的數據        map.set(this, value);    } else {        // 第一次設置線程變量,則會創建ThreadLocalMap        createMap(t, value);    }    }

再看下get方法:7HP28資訊網——每日最新資訊28at.com

public T get() {    // 獲取當前線程(調用方線程:主線程、線程1......)    Thread t = Thread.currentThread();    // 當前線程作為key,獲取對應的線程變量ThreadLocalMap    ThreadLocalMap map = getMap(t);    if (map != null) {        // 值最終是存在Entry對象的value屬性        ThreadLocalMap.Entry e = map.getEntry(this);        if (e != null) {            T result = (T)e.value;            return result;        }    }    // ThreadLocalMap為空,則初始化操作    return setInitialValue();} private T setInitialValue() {    // 創建ThreadLocal時可重寫初始化方法    T value = initialValue();    // 獲取當前線程(調用方線程:主線程、線程1......)    Thread t = Thread.currentThread();    // 當前線程作為key,獲取對應的線程變量ThreadLocalMap    ThreadLocalMap map = getMap(t);    if (map != null) {        // 設置線程變量:key為當前定義的ThreadLocal實例的this引用,值為初始化方法返回的數據        map.set(this, value);     } else {        // 第一次設置線程變量,則會創建ThreadLocalMap        createMap(t, value);     }        return value;}

InheritableThreadLocal:7HP28資訊網——每日最新資訊28at.com

private static InheritableThreadLocal<String> testInheritableThreadLocal = new InheritableThreadLocal<>();    public static void main(String[] args) {        // 主線程        testInheritableThreadLocal.set("zhangsan");        System.out.println("userName0: " + testInheritableThreadLocal.get());                // 線程1        new Thread(() -> System.out.println("userName1: " + testInheritableThreadLocal.get())).start();        // 線程2        new Thread(() -> System.out.println("userName2: " + testInheritableThreadLocal.get())).start();    }#結果輸出userName0: zhangsanuserName1: zhangsanuserName2: zhangsan

查看InheritableThreadLocal的源碼:7HP28資訊網——每日最新資訊28at.com

public class InheritableThreadLocal<T> extends ThreadLocal<T> {     protected T childValue(T parentValue) {        return parentValue;    }       ThreadLocalMap getMap(Thread t) {       return t.inheritableThreadLocals;    }    void createMap(Thread t, T firstValue) {        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);    }}

InheritableThreadLocal繼承了ThreadLocal類型,并且重寫了getMap和createMap方法,唯一的區別是:threadLocals(ThreadLocalMap類型)變成了inheritableThreadLocals(ThreadLocalMap類型)。7HP28資訊網——每日最新資訊28at.com

查看get方法:7HP28資訊網——每日最新資訊28at.com

public T get() {        Thread t = Thread.currentThread();        // 注意:InheritableThreadLocal重寫了getMap方法,返回inheritableThreadLocals        ThreadLocalMap map = getMap(t);        if (map != null) {            ThreadLocalMap.Entry e = map.getEntry(this);            if (e != null) {                T result = (T)e.value;                return result;            }        }        return setInitialValue();    }

查看inheritableThreadLocals設置的地方,最終定位到java.lang.Thread#init方法:7HP28資訊網——每日最新資訊28at.com

private void init(ThreadGroup g, Runnable target, String name,  long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {        if (name == null) {            throw new NullPointerException("name cannot be null");        }        this.name = name;        Thread parent = currentThread();        SecurityManager security = System.getSecurityManager();        if (g == null) {            if (security != null) {                g = security.getThreadGroup();            }            if (g == null) {                g = parent.getThreadGroup();            }        }        g.checkAccess();        if (security != null) {            if (isCCLOverridden(getClass())) {                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);            }        }        g.addUnstarted();        this.group = g;        this.daemon = parent.isDaemon();        this.priority = parent.getPriority();        if (security == null || isCCLOverridden(parent.getClass()))            this.contextClassLoader = parent.getContextClassLoader();        else            this.contextClassLoader = parent.contextClassLoader;        this.inheritedAccessControlContext =                acc != null ? acc : AccessController.getContext();        this.target = target;        setPriority(priority);        if (inheritThreadLocals && parent.inheritableThreadLocals != null)           // 將父線程inheritableThreadLocals復制給子線程inheritableThreadLocals           // 此處可聯想到:如果使用了線程池,而線程池中的線程是復用的,不會再次調用初始化方法           // 所以無法將父線程inheritableThreadLocals復制給子線程inheritableThreadLocals            this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);        this.stackSize = stackSize;        tid = nextThreadID();    }

三、注意事項

  • 使用ThreadLocal、或者InheritableThreadLocal方法時,注意及時調用remove方法進行清理。
  • 注意線程池結合InheritableThreadLocal的使用,線程池中的線程是復用的,不會再次調用初始化方法,所以無法將父線程inheritableThreadLocals復制給子線程inheritableThreadLocals。

本文鏈接:http://www.tebozhan.com/showinfo-26-12355-0.htmlThreadLocal和InheritableThreadLocal詳解

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: API接口脫敏:如何安全地處理敏感數據?

下一篇: Java中使用正則表達式

標簽:
  • 熱門焦點
  • 7月安卓手機性價比榜:努比亞+紅魔兩款新機入榜

    7月登場的新機有努比亞Z50S Pro和紅魔8S Pro,除了三星之外目前唯二的兩款搭載超頻版驍龍8Gen2處理器的產品,而且努比亞和紅魔也一貫有著不錯的性價比,所以在本次的性價比榜單
  • 6月iOS設備性能榜:M2穩居榜首 A系列只能等一手3nm來救

    沒有新品發布,自然iOS設備性能榜的上榜設備就沒有什么更替,僅僅只有跑分變化而產生的排名變動,畢竟蘋果新品的發布節奏就是這樣的,一年下來也就幾個移動端新品,不會像安卓廠商,一
  • 6月安卓手機性能榜:vivo/iQOO霸占旗艦排行榜前三

    2023年上半年已經正式過去了,我們也迎來了安兔兔V10版本,在新的驍龍8Gen3和天璣9300發布之前,性能榜的榜單大體會以驍龍8Gen2和天璣9200+為主,至于那顆3.36GHz的驍龍8Gen2領先
  • 把LangChain跑起來的三個方法

    使用LangChain開發LLM應用時,需要機器進行GLM部署,好多同學第一步就被勸退了,那么如何繞過這個步驟先學習LLM模型的應用,對Langchain進行快速上手?本片講解3個把LangChain跑起來
  • SpringBoot中使用Cache提升接口性能詳解

    環境:springboot2.3.12.RELEASE + JSR107 + Ehcache + JPASpring 框架從 3.1 開始,對 Spring 應用程序提供了透明式添加緩存的支持。和事務支持一樣,抽象緩存允許一致地使用各
  • Python異步IO編程的進程/線程通信實現

    這篇文章再講3種方式,同時講4中進程間通信的方式一、 Python 中線程間通信的實現方式共享變量共享變量是多個線程可以共同訪問的變量。在Python中,可以使用threading模塊中的L
  • 共享單車的故事講到哪了?

    來源丨海克財經與共享充電寶相差不多,共享單車已很久沒有被國內熱點新聞關照到了。除了一再漲價和用戶直呼用不起了。近日多家媒體再發報道稱,成都、天津、鄭州等地多個共享單
  • 10天營收超1億美元,《星鐵》比《原神》差在哪?

    來源:伯虎財經作者:陳平安即便你沒玩過《原神》,你一定聽說過的它的大名。恨它的人把《原神》開服那天稱作是中國游戲史上最黑暗的一天,有粉絲因為索尼在PS平臺上線《原神》,怒而
  • 騰訊VS網易,最卷游戲暑期檔,誰能笑到最后?

    作者:無銹缽來源:財經無忌7月16日晚,上海1862時尚藝術中心。伴隨著幻象的精準命中,碩大的熒幕之上,比分被定格在了14:12,被寄予厚望的EDG戰隊以絕對的優勢戰勝了BLG戰隊,拿下了總決
Top