日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

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

ThreadLocal和InheritableThreadLocal詳解

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

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

一、概述

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

二、案例介紹

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

查看get方法:App28資訊網——每日最新資訊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方法:App28資訊網——每日最新資訊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.www897cc.com/showinfo-26-12355-0.htmlThreadLocal和InheritableThreadLocal詳解

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

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

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

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 凤翔县| 礼泉县| 西乌珠穆沁旗| 东台市| 阳江市| 麦盖提县| 故城县| 浪卡子县| 常宁市| 嘉定区| 游戏| 慈利县| 江源县| 恩平市| 长春市| 东明县| 扶余县| 包头市| 河池市| 册亨县| 临沧市| 桂阳县| 枝江市| 壤塘县| 洛隆县| 灵武市| 博乐市| 南宫市| 夏河县| 密山市| 敦化市| 浙江省| 浠水县| 甘孜| 龙山县| 鲜城| 石门县| 阜宁县| 丹江口市| 阿克陶县| 岱山县|