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

當(dāng)前位置:首頁 > 科技  > 軟件

ThreadLocal和InheritableThreadLocal詳解

來源: 責(zé)編: 時(shí)間:2023-10-08 07:05:54 291觀看
導(dǎo)讀一、概述為了方便且更加安全的進(jìn)行多線程編程,jdk引入ThreadLocal和InheritableThreadLocal兩個(gè)類,以供開發(fā)人員進(jìn)行多線程之間的數(shù)據(jù)傳遞和數(shù)據(jù)共享。InheritableThreadLocal是ThreadLocal的子類,它可以實(shí)現(xiàn)子線程共享

ANo28資訊網(wǎng)——每日最新資訊28at.com

一、概述

為了方便且更加安全的進(jìn)行多線程編程,jdk引入ThreadLocal和InheritableThreadLocal兩個(gè)類,以供開發(fā)人員進(jìn)行多線程之間的數(shù)據(jù)傳遞和數(shù)據(jù)共享。InheritableThreadLocal是ThreadLocal的子類,它可以實(shí)現(xiàn)子線程共享父線程的變量。ANo28資訊網(wǎng)——每日最新資訊28at.com

二、案例介紹

ThreadLocal:ANo28資訊網(wǎng)——每日最新資訊28at.com

private static ThreadLocal<String> testThreadLocal = new ThreadLocal<>();/*// 創(chuàng)建時(shí)可重寫初始化方法ThreadLocal<String> testThreadLocal = new ThreadLocal<String>(){    public Connection initialValue(){        return "zhangsan";    }};*/public static void main(String[] args) {        // 設(shè)置線程變量        testThreadLocal.set("zhangsan");        // 獲取線程變量        String userName = testThreadLocal.get();        System.out.println("userName: " + userName);        // 刪除線程變量        testThreadLocal.remove();        userName = testThreadLocal.get();        System.out.println("userName: " + userName);}#結(jié)果輸出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();}#結(jié)果輸出【線程之間變量相關(guān)隔離】userName0: zhangsanuserName1: lisiuserName2: wangwu

接下來看下set方法:ANo28資訊網(wǎng)——每日最新資訊28at.com

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

再看下get方法:ANo28資訊網(wǎng)——每日最新資訊28at.com

public T get() {    // 獲取當(dāng)前線程(調(diào)用方線程:主線程、線程1......)    Thread t = Thread.currentThread();    // 當(dāng)前線程作為key,獲取對應(yīng)的線程變量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() {    // 創(chuàng)建ThreadLocal時(shí)可重寫初始化方法    T value = initialValue();    // 獲取當(dāng)前線程(調(diào)用方線程:主線程、線程1......)    Thread t = Thread.currentThread();    // 當(dāng)前線程作為key,獲取對應(yīng)的線程變量ThreadLocalMap    ThreadLocalMap map = getMap(t);    if (map != null) {        // 設(shè)置線程變量:key為當(dāng)前定義的ThreadLocal實(shí)例的this引用,值為初始化方法返回的數(shù)據(jù)        map.set(this, value);     } else {        // 第一次設(shè)置線程變量,則會創(chuàng)建ThreadLocalMap        createMap(t, value);     }        return value;}

InheritableThreadLocal:ANo28資訊網(wǎng)——每日最新資訊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();    }#結(jié)果輸出userName0: zhangsanuserName1: zhangsanuserName2: zhangsan

查看InheritableThreadLocal的源碼:ANo28資訊網(wǎng)——每日最新資訊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方法,唯一的區(qū)別是:threadLocals(ThreadLocalMap類型)變成了inheritableThreadLocals(ThreadLocalMap類型)。ANo28資訊網(wǎng)——每日最新資訊28at.com

查看get方法:ANo28資訊網(wǎng)——每日最新資訊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設(shè)置的地方,最終定位到j(luò)ava.lang.Thread#init方法:ANo28資訊網(wǎng)——每日最新資訊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復(fù)制給子線程inheritableThreadLocals           // 此處可聯(lián)想到:如果使用了線程池,而線程池中的線程是復(fù)用的,不會再次調(diào)用初始化方法           // 所以無法將父線程inheritableThreadLocals復(fù)制給子線程inheritableThreadLocals            this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);        this.stackSize = stackSize;        tid = nextThreadID();    }

三、注意事項(xiàng)

  • 使用ThreadLocal、或者InheritableThreadLocal方法時(shí),注意及時(shí)調(diào)用remove方法進(jìn)行清理。
  • 注意線程池結(jié)合InheritableThreadLocal的使用,線程池中的線程是復(fù)用的,不會再次調(diào)用初始化方法,所以無法將父線程inheritableThreadLocals復(fù)制給子線程inheritableThreadLocals。

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

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

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

下一篇: Java中使用正則表達(dá)式

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 南溪县| 邓州市| 慈利县| 廉江市| 巴南区| 定日县| 延安市| 新泰市| 铅山县| 呼图壁县| 南华县| 镇赉县| 景洪市| 黎平县| 通化市| 平昌县| 棋牌| 宿松县| 郯城县| 宜阳县| 光泽县| 莱州市| 道孚县| 府谷县| 泸州市| 洪江市| 铜鼓县| 汶上县| 乌鲁木齐县| 项城市| 安庆市| 宁夏| 彭水| 桑日县| 南部县| 和田县| 北碚区| 达日县| 扶绥县| 崇礼县| 宾阳县|