我已经阅读了很多关于为什么ThreadLocal
变量需要是静态的文章(尽管没有必要),但我不知道为什么它应该是静态的。
我已经阅读了here和许多其他链接,但没有明白这一点。
我做过类似的事情
public class ThreadLocalDemo{
public static void main(String[]args)throws Exception{
SharedRersource r1= new SharedRersource();
Thread t1= new Thread(r1);
Thread t2= new Thread(r1);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Main thread Exiting...");
}
}
class SharedRersource implements Runnable{
private ThreadLocal<Integer> threadId = new ThreadLocal(){
protected Integer initialValue(){
return (int)(Math.random()*100);
}
};
public void run(){
try{
Thread.sleep(2000);
}
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(threadId.get());
}
};
此处主题t1和t2拥有threadId的私有副本,而不是为什么它应该是静态的
请更好地了解我。 谢谢
答案 0 :(得分:6)
这个问题的答案在于ThreadLocal实现。
将ThreadLocal视为容器
ThreadLocal
是一个内部ThreadLocalMap
的容器,这个ThreadLocalMap
是threadlocal需要静态的关键(尽管不是必需的,但是建议)保持静止)。
因为我们想要 single container per class
,not container per instance
。如果我们每个实例都有容器,那么我们将拥有与实例一样多的容器,这会产生内存泄漏。 强>
这里有更多细节
答案 1 :(得分:2)
根据您的实施,您({逻辑上) 4个不同的实例 threadID
:
r1.threadID{t1}
- 保存在资源r1
中并由线程t1
观察的实例。如果它将被中断,它将由线程t1
打印。
r2.threadID{t2}
- 保存在资源r2
中并由线程t2
观察的实例。如果它将被中断,它将由线程t2
打印。
r1.threadID{t2}
- 保存在资源r1
中并由线程t2
观察的实例,例如,如果它(直接)调用r1.run()
。
r2.threadID{t2}
- 保存在资源r2
中并由线程t1
观察的实例,例如,如果它(直接)调用r2.run()
。
您不太可能需要第3和第4个实例,因此您可以:
在这种情况下,您将拥有两个实例:threadID{t1}
,由线程t1
观察到,threadID{t2}
,线程{{ 1}}。
在这种情况下,您将拥有两个实例:t2
,通过r1.threadID
(通过主题r1
)和t1
观察,通过r2.threadID
(线程r2
)观察到。
答案 2 :(得分:0)
没有固有的原因ThreadLocal
变量需要是静态的。就是这样,ThreadLocal
解决的问题通常只发生在基于静态设计思想的程序中。
IMO,您最有可能在最初是单线程的代码中找到ThreadLocal
,直到有人升级&#34;它使用多个线程。当大量代码最初引用某些 static 变量时,本地线程就派上用场了,现在你需要每个运行在同一代码体中的线程都拥有自己的副本。 / p>
IMO,ThreadLocal
是一种代码气味 - 一种不良设计的标志。一个设计良好的多线程程序不应该需要它。
答案 3 :(得分:0)
ThreadLocal
不需要static
。就像任何其他变量一样,这取决于您的意图:
public class FooClass {
static Integer staticVar // 1 per process
Integer var; // 1 per instance
static ThreadLocal<Integer> staticThreadLocalVar; // 1 per thread
ThreadLocal<Integer> threadLocalVar; // 1 per thread per instance
}
您提供的报价完全是指上面列出的第三种情况。
ThreadLocal 实例通常是类中的私有静态字段 希望将州与线程
相关联
但是,在某些情况下,将状态与每个实例的线程相关联可能是完全合理的,在这种情况下,您可能希望使用non-static
ThreadLocal
代替(第四种情况)。