InheritableThreadLocal

简介

主要是用来解决Threadlocal无法传递变量到子线程的不足。

应用

用户登录退出场景。

public class InheritableThreadLocalDemo {
    private static final InheritableThreadLocal<String> curName = new InheritableThreadLocal<>();

    public void login(String name) {
        System.out.println(name + " login");
        curName.set(name);
    }

    public void getCur() {
        String s = curName.get();
        System.out.println(s + " get");
        new Thread(
                ()->{
                    System.out.println("子线程获取name:"+curName.get());
                }
        ).start();
    }

    public void logout() {
        System.out.println(curName.get() + " logout");
        curName.remove();
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        InheritableThreadLocalDemo threadLocalDemo = new InheritableThreadLocalDemo();
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.execute(() -> {

            threadLocalDemo.login(1 + "");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            threadLocalDemo.getCur();
            threadLocalDemo.logout();
        });
        executorService.execute( () -> {
            threadLocalDemo.login(2 + "");
            threadLocalDemo.getCur();
            threadLocalDemo.logout();
        });
        System.out.println("---------");
    }
}

可以看到,子线程成功获取到父线程的变量。

1 login
---------
2 login
2 get
2 logout
子线程获取name:2
1 get
1 logout
子线程获取name:1

核心原理

InheritableThreadLocal使用的是Thread的 inheritableThreadLocals属性。

在Thread初始化的时候:

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc,
                  boolean inheritThreadLocals) {
...
//当父线程的inheritableThreadLocals不为null,就会把其复制给当前线程。
 if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
...                  

需要注意的是,只有在子线程创建的时候,才会复制父线程的inheritableThreadLocals。后续2者之间再发生变量变化,是互相不会影响的。

如果想要随时更新变量,可以查看TransmittableThreadLocal

Last updated

Was this helpful?