InheritableThreadLocal类

InheritableThreadLocal类的作用

InheritableThreadLocal类可使子线程继承父线程的值
示例代码:

public class StaticThreadLocal {
    public static InheritableThreadLocal<Object> itl = new InheritableThreadLocal<>();
}
class MyThreadX extends Thread{

    @Override
    public void run() {
        try {
            for(int i=0;i<5;i++){
                System.out.println("MyThreadX中取值=>"+StaticThreadLocal.itl.get());
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}

class TestMtl{
    public static void main(String[] args) throws InterruptedException {
        for(int i=0;i<5;i++){
            if(StaticThreadLocal.itl.get()==null){
                StaticThreadLocal.itl.set("main");
            }
            Thread.sleep(1000);
            System.out.println("main中取值=>"+StaticThreadLocal.itl.get());
        }
        Thread.sleep(2000);
        MyThreadX myThreadX = new MyThreadX();
        myThreadX.start();
    }
}
执行结果:
	main中取值=>main
	main中取值=>main
	main中取值=>main
	main中取值=>main
	main中取值=>main
	MyThreadX中取值=>main
	MyThreadX中取值=>main
	MyThreadX中取值=>main
	MyThreadX中取值=>main
	MyThreadX中取值=>main

InheritableThreadLocal类源码

InheritableThreadLocal类继承ThreadLocal类,源码如下:

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
  
    protected T childValue(T parentValue) {
        return parentValue;
    }
    
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }
	//创建一个ThreadLocalMap,将其赋值给inheritableThreadLocals ,inheritableThreadLocals 是Thread
	//类的实例变量类型为ThreadLocal.ThreadLocalMap
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }
}

父子线程的inheritableThreadLocals 变量是相互独立的

线程在创建的时候会判断其父线程的inheritableThreadLocals 变量是否为null,不为null就将父线程的inheritableThreadLocals变量赋值给子线程的inheritableThreadLocals变量,赋值源码如下所示:

if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

由源码可知线程创建初始赋值的时候新建了一个ThreadLocalMap,所以父线程的inheritableThreadLocals变量和子线程的inheritableThreadLocals是相互独立的。因此子线程创建之后父线程中的inheritableThreadLocals变量值改变,子线程的值是不会跟着改变的。同理子线程inheritableThreadLocals变量有了新值,父线程的inheritableThreadLocals变量也不会跟着改变。
改变父线程的值子线程的值未改变示例代码如下:

public class StaticThreadLocal {
    public static InheritableThreadLocal<Object> itl = new InheritableThreadLocal<>();
}
class MyThreadX extends Thread{

    @Override
    public void run() {
        try {
            for(int i=0;i<5;i++){
                System.out.println("MyThreadX中类中取值=>"+StaticThreadLocal.itl.get());
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}

class TestMtl{
    public static void main(String[] args) throws InterruptedException {
        for(int i=0;i<5;i++){
            if(StaticThreadLocal.itl.get()==null){
                StaticThreadLocal.itl.set("main");
            }
            System.out.println("main中取值=>"+StaticThreadLocal.itl.get());
        }
        Thread.sleep(2000);
        MyThreadX myThreadX = new MyThreadX();
        myThreadX.start();
        Thread.sleep(1000);
        StaticThreadLocal.itl.set("main改变了!");
        System.out.println("main中取值=>"+StaticThreadLocal.itl.get());
    }
}
执行结果:
	main中取值=>main
	main中取值=>main
	main中取值=>main
	main中取值=>main
	main中取值=>main
	MyThreadX中类中取值=>main
	MyThreadX中类中取值=>main
	main中取值=>main改变了!
	MyThreadX中类中取值=>main
	MyThreadX中类中取值=>main
	MyThreadX中类中取值=>main

改变子线程的值父线程的值未改变代码示例:

public class StaticThreadLocal {
    public static InheritableThreadLocal<Object> itl = new InheritableThreadLocal<>();
}
class MyThreadX extends Thread{

    @Override
    public void run() {
        try {
            for(int i=0;i<5;i++){
                System.out.println("MyThreadX中类中取值=>"+StaticThreadLocal.itl.get());
                if(i==2){
                    StaticThreadLocal.itl.set("MyThreadX改变了!");
                }
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}

class TestMtl{
    public static void main(String[] args) throws InterruptedException {
        for(int i=0;i<5;i++){
            if(StaticThreadLocal.itl.get()==null){
                StaticThreadLocal.itl.set("main");
            }
            System.out.println("main中取值=>"+StaticThreadLocal.itl.get());
        }
        Thread.sleep(2000);
        MyThreadX myThreadX = new MyThreadX();
        myThreadX.start();
        Thread.sleep(5000);
        System.out.println("--main中取值=>"+StaticThreadLocal.itl.get());
    }
}
执行结果:
	main中取值=>main
	main中取值=>main
	main中取值=>main
	main中取值=>main
	main中取值=>main
	MyThreadX中类中取值=>main
	MyThreadX中类中取值=>main
	MyThreadX中类中取值=>main
	MyThreadX中类中取值=>MyThreadX改变了!
	MyThreadX中类中取值=>MyThreadX改变了!
	--main中取值=>main

如果父线程或子线程改变了inheritableThreadLocals变量中存储的对象的属性值,则他们可以获取到被改变的属性值

上面说的父子线程的inheritableThreadLocals 变量值改变不会相互影响,如果是父线程改变了inheritableThreadLocals变量中存储的对象的属性,那么子线程是可以获取到改变后的属性值的。
示例代码如下:

class User{
    String name;
    int age;

    public User(String name,int age){
        this.name = name;
        this.age = age;
    }
    这里省略get、set方法...
}

public class StaticThreadLocal {
    public static InheritableThreadLocal<User> itl = new InheritableThreadLocal<>();
}
class MyThreadX extends Thread{

    @Override
    public void run() {
        try {
            for(int i=0;i<5;i++){
                Thread.sleep(1000);
                System.out.println("MyThreadX中取出姓名=>"
                +StaticThreadLocal.itl.get().getName()
                +"  年龄=>"+StaticThreadLocal.itl.get().getAge());
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}

class TestMtl{
    public static void main(String[] args) throws InterruptedException {
        User user = new User("康康", 10);
        StaticThreadLocal.itl.set(user);
        MyThreadX myThreadX = new MyThreadX();
        myThreadX.start();
        Thread.sleep(2000);
        user.setName("胖虎");
        user.setAge(12);
        System.out.println("user属性改变了!");
    }
}
执行结果:
MyThreadX中取出姓名=>康康  年龄=>10
MyThreadX中取出姓名=>康康  年龄=>10
user属性改变了!
MyThreadX中取出姓名=>胖虎  年龄=>12
MyThreadX中取出姓名=>胖虎  年龄=>12
MyThreadX中取出姓名=>胖虎  年龄=>12

同样在子线程中改变inheritableThreadLocals变量中存储的对象的属性值父线程中取到的也是改变后的。
实例代码如下:

class User{
    String name;
    int age;

    public User(String name,int age){
        this.name = name;
        this.age = age;
    }
    这里省略get、set方法...
}
public class StaticThreadLocal {
    public static InheritableThreadLocal<User> itl = new InheritableThreadLocal<>();
}
class MyThreadX extends Thread{

    @Override
    public void run() {
        try {
            for(int i=0;i<5;i++){
                Thread.sleep(1000);
                System.out.println("MyThreadX中取出姓名=>"+
                StaticThreadLocal.itl.get().getName()+
                "  年龄=>"+StaticThreadLocal.itl.get().getAge());
                if(i==2){
                    StaticThreadLocal.itl.get().setName("胖虎");
                    StaticThreadLocal.itl.get().setAge(12);
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}

class TestMtl{
    public static void main(String[] args) throws InterruptedException {
        User user = new User("康康", 10);
        StaticThreadLocal.itl.set(user);
        MyThreadX myThreadX = new MyThreadX();
        myThreadX.start();
        Thread.sleep(6000);
        System.out.println("main中取出姓名=>"+StaticThreadLocal.itl.get().getName()+"  年龄=>"+StaticThreadLocal.itl.get().getAge());
    }
}
执行结果:
	MyThreadX中取出姓名=>康康  年龄=>10
	MyThreadX中取出姓名=>康康  年龄=>10
	MyThreadX中取出姓名=>康康  年龄=>10
	MyThreadX中取出姓名=>胖虎  年龄=>12
	MyThreadX中取出姓名=>胖虎  年龄=>12
	main中取出姓名=>胖虎  年龄=>12

重写InheritableThreadLocal类中的childValue方法,子线程可以在childValue方法中修改从父线程继承过来的值

示例代码如下:

class MyInheritableThreadLocal extends InheritableThreadLocal<Object>{
    @Override
    protected Object childValue(Object parentValue) {
        return parentValue+"-childValue";
    }
}

class StaticThreadLocal {
    public static MyInheritableThreadLocal itl = new MyInheritableThreadLocal();
}
class MyThreadX extends Thread{

    @Override
    public void run() {
        try {
            for(int i=0;i<5;i++){
                System.out.println("MyThreadX=>"+StaticThreadLocal.itl.get());
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}

class TestMtl{
    public static void main(String[] args) throws InterruptedException {
        StaticThreadLocal.itl.set("main");
        MyThreadX myThreadX = new MyThreadX();
        myThreadX.start();
        Thread.sleep(2000);
        System.out.println("main=>"+StaticThreadLocal.itl.get());
    }
}
执行结果:
	MyThreadX=>main-childValue
	MyThreadX=>main-childValue
	main=>main
	MyThreadX=>main-childValue
	MyThreadX=>main-childValue
	MyThreadX=>main-childValue

它和使用InheritableThreadLocal.set()方法赋值的区别是:
InheritableThreadLocal.set()可以赋任意次新值而重写的childValue方法只会在子线程创建的时候执行一次

参考书籍:Java多线程编程核心技术(第2版)高洪岩 著

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值