InheritableThreadLocal 如何为实例变量线程工作?

How does InheritableThreadLocal work for instance variable thread?

我有以下程序

class ParentThread extends Thread{

    public ParentThread(String s) {
        super(s);
    }

    static InheritableThreadLocal tl = new InheritableThreadLocal();
    ChildThread c = new ChildThread("child");

    @Override
    public void run() {
        tl.set("pp");
        System.out.println("Thread :"+Thread.currentThread().getName()+" thread local value: "+tl.get());
        c.start();
    }
}
class ChildThread extends Thread{
    public ChildThread(String child) {
        super(child);
    }

    @Override
    public void run() {
        System.out.println("Thread :"+Thread.currentThread().getName()+" thread local value: "+ParentThread.tl.get());
    }
}
public class ThreadLocalDemo {
    public static void main(String[] args) {
        ParentThread p = new ParentThread("parent");
        p.start();
    }
}

我得到的输出为

Thread :parent thread local value: pp
Thread :child thread local value: null

我相信即使我将 ChildThread 声明为实例变量,parent 线程 运行 方法负责创建 child 线程。那么,为什么 child 的输出为空?

当我把这个

ChildThread c = new ChildThread("child");

在 运行 方法中,我确实得到了 pp。为什么会这样?

来自 API 文档:

when a child thread is created, the child receives initial values for all inheritable thread-local variables for which the parent has values.

让我们在不更改任何实现的情况下重写 ParentThread 以使其更加明确。 (没有特别的理由在演示中使用 ParentThread - 主线程会做的很好。编辑:我应该继续这个想法。ChildThread 实例继承可继承来自 主线程 的线程局部变量,而不是 ParentThread 实例。)

class ParentThread extends Thread{
    static InheritableThreadLocal tl;
    static {
        tl = new InheritableThreadLocal();
    }

    /* pp */ ChildThread c;

    public ParentThread(String s) {
        super(s);
        this.c = new ChildThread("child");
    }

    @Override
    public void run() {
        tl.set("pp");
        System.out.println("Thread :"+Thread.currentThread().getName()+" thread local value: "+tl.get());
        c.start();
    }
}

我们看到 ChildThread 构造函数在 InheritableThreadLocal.set 之前被调用。在tl.set(pp);后面写new ChildThread(),应该可以看到值

InheritableThreadLocal 疯了。我会避免它,除非做一些恶意的事情。

总的来说,我强烈建议避免不必要的子类化,ThreadLocal