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

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

ThreadLocal和InheritableThreadLocal詳解

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

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

一、概述

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

二、案例介紹

ThreadLocal:ZEg28資訊網——每日最新資訊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方法:ZEg28資訊網——每日最新資訊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方法:ZEg28資訊網——每日最新資訊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:ZEg28資訊網——每日最新資訊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的源碼:ZEg28資訊網——每日最新資訊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類型)。ZEg28資訊網——每日最新資訊28at.com

查看get方法:ZEg28資訊網——每日最新資訊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方法:ZEg28資訊網——每日最新資訊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中使用正則表達式

標簽:
  • 熱門焦點
  • 一加Ace2 Pro真機揭曉 鈦空灰配色質感拉滿

    終于,在經過了幾波預熱之后,一加Ace2 Pro的外觀真機圖在網上出現了。還是博主數碼閑聊站曝光的,這次的外觀設計還是延續了一加11的方案,只是細節上有了調整,例如新加入了鈦空灰
  • iPhone賣不動了!蘋果股價創年內最大日跌幅:市值一夜蒸發萬億元

    8月5日消息,今天凌晨美股三大指數高開低走集體收跌,道指跌0.41%;納指跌0.36%;標普500指數跌0.52%。熱門科技股也都變化極大,其中蘋果報181.99美元,跌4.8%,創
  • 三言兩語說透設計模式的藝術-簡單工廠模式

    一、寫在前面工廠模式是最常見的一種創建型設計模式,通常說的工廠模式指的是工廠方法模式,是使用頻率最高的工廠模式。簡單工廠模式又稱為靜態工廠方法模式,不屬于GoF 23種設計
  • K6:面向開發人員的現代負載測試工具

    K6 是一個開源負載測試工具,可以輕松編寫、運行和分析性能測試。它建立在 Go 和 JavaScript 之上,它被設計為功能強大、可擴展且易于使用。k6 可用于測試各種應用程序,包括 Web
  • CSS單標簽實現轉轉logo

    轉轉品牌升級后更新了全新的Logo,今天我們用純CSS來實現轉轉的新Logo,為了有一定的挑戰性,這里我們只使用一個標簽實現,將最大化的使用CSS能力完成Logo的繪制與動畫效果。新logo
  • JavaScript學習 -AES加密算法

    引言在當今數字化時代,前端應用程序扮演著重要角色,用戶的敏感數據經常在前端進行加密和解密操作。然而,這樣的操作在網絡傳輸和存儲中可能會受到惡意攻擊的威脅。為了確保數據
  • Temu起訴SHEIN,跨境電商戰事升級

    來源 | 伯虎財經(bohuFN)作者 | 陳平安日前據外媒報道,拼多多旗下跨境電商平臺Temu正對競爭對手SHEIN提起新訴訟,訴狀稱Shein&ldquo;利用市場支配力量強迫服裝廠商與之簽訂獨家
  • 華為將推出盤古數字人大模型 可幫助用戶12小時完成數字人生成

    在今日舉行的2023年華為云數字文娛AI創新峰會上,華為云全球Marketing與銷售服務總裁石冀琳表示,華為云將在后續推出盤古數字人大模型,可幫助用戶12小
  • 榮耀Magic4 至臻版 首創智慧隱私通話 強勁影音系統

    2022年第一季度臨近尾聲,在該季度內,許多品牌陸續發布自己的最新產品,讓大家從全新的角度來了解當今的手機技術。手機是電子設備中,更新迭代十分迅速的一款產品,基
Top