【问题标题】:How does InheritableThreadLocal work for instance variable thread?InheritableThreadLocal 如何为实例变量线程工作?
【发布时间】:2020-11-06 05:07:30
【问题描述】:

我有以下程序

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 声明为实例变量,父线程的 run 方法也负责创建子线程。那么,为什么孩子的输出为空?

当我放这个

ChildThread c = new ChildThread("child");

在run方法里面,我确实得到了pp。为什么会这样?

【问题讨论】:

    标签: java multithreading thread-local


    【解决方案1】:

    来自 API 文档:

    当子线程被创建时,子线程接收初始值 父级拥有的所有可继承线程局部变量 价值观。

    让我们重写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

    【讨论】:

    • 我很困惑,因为就像你说的那样,在 API 文档中,它说“当创建子线程时,子线程接收初始值......”,但只创建子线程当我们执行 child.start() 时,& 在此之前我已经设置了“pp”
    • Thread 对象创建时。 start 只是开始执行现有线程。
    猜你喜欢
    • 2011-11-09
    • 2012-09-20
    • 2023-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    相关资源
    最近更新 更多