【发布时间】:2020-04-04 21:08:22
【问题描述】:
我希望 ParentThread 将 threadId 设置为传递给其构造函数的值(例如 p1)。然后它的所有孩子都将threadId 设置为p1.c1、p1.c2 等等。我写了以下代码:
public class InheritableThreadLocalDemo {
public static void main(String[] args)
{
ParentThread pt = new ParentThread("p1");
pt.start();
}
}
class ParentThread extends Thread {
static int childCount = 0;
public static InheritableThreadLocal threadId = new InheritableThreadLocal() {
public Object childValue(Object parentValue)
{
return parentValue.toString() + ".c" + (++childCount) ; //this is line 18 where NullPointerException is occuring
}
};
public ParentThread(String pThreadId) {
threadId.set(pThreadId);
}
public void run()
{
System.out.println("Thread id:" + threadId.get());
ChildThread childThread1 = new ChildThread();
childThread1.start();
ChildThread childThread2 = new ChildThread();
childThread2.start();
}
}
class ChildThread extends Thread {
public void run()
{
System.out.println("Child Thread Value :" + ParentThread.threadId.get());
}
}
打印出来:
Thread id:null
Exception in thread "Thread-0" java.lang.NullPointerException
at com.mahesha999.examples.java.multithreading.ParentThread$1.childValue(InheritableThreadLocalDemo.java:18)
at java.lang.ThreadLocal$ThreadLocalMap.<init>(Unknown Source)
at java.lang.ThreadLocal$ThreadLocalMap.<init>(Unknown Source)
at java.lang.ThreadLocal.createInheritedMap(Unknown Source)
at java.lang.Thread.init(Unknown Source)
at java.lang.Thread.init(Unknown Source)
at java.lang.Thread.<init>(Unknown Source)
at com.mahesha999.examples.java.multithreading.ChildThread.<init>(InheritableThreadLocalDemo.java:37)
at com.mahesha999.examples.java.multithreading.ParentThread.run(InheritableThreadLocalDemo.java:30)
我在eclipse中调试,发现里面的构造函数threadId被正确设置为p1,但是在ParentThread.run()里面,读作null。此外,在 childValue 内部,.toString() 被调用 null,抛出 NullPointerException。
Q1. *为什么构造函数中设置的值在run()和childValue()中不可见?
我也想要这个ParentClass 可重复使用,也就是说我应该能够拥有类似的系列
-
p2.c1、p2.c2等 -
p3.c1、p3.c2等 - 等等
我觉得,为此,我应该将childCount 和threadId 设为非静态。但是从这两个变量中删除 static 会给我编译时错误
Cannot make a static reference to the non-static field ParentThread.threadId
在ChildThread.run() 内,用于ParentThread.threadId.get()。但是,现在我无法想象如何使这些 InheritableThreadLocal 变量在每个实例的每个线程中唯一。
Q2.我该怎么做?
Q3. 还是在这里遗漏了一些愚蠢的东西? “每个实例每个线程唯一”只不过是“每个实例唯一”,在这种情况下我们根本不需要线程本地的概念吗?这就是为什么所有ThreadLocal 变量都应该按约定为static 的原因吗?
【问题讨论】:
标签: java multithreading thread-local inheritable-thread-local