I have read many articles on why ThreadLocal
variable need to be static(although not necessary), but I didn't get the idea why it should be static.
I have read it here and many other links but didn't get the idea.
I have done something like this
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());
}
};
Here thread t1 and t2 is having private copy of threadId than why It should be static
Please give a better understanding to me. Thanks
Answer to this question lies into ThreadLocal implementation .
Think ThreadLocal as a container
ThreadLocal
is a container that maintain a ThreadLocalMap
internally , This ThreadLocalMap
is the key why threadlocal need to be static(although not necessary ,but suggestion is keep it static).
Because we want single container per class
, not container per instance
.If we have container per instance we will be having as many container as instance and that will created memory leak .
More detail here
With your implementation you have (logically) 4 different instances of threadID
:
r1.threadID{t1}
- Instance saved in resource r1
and observed by thread t1
. It will be printed by thread t1
if it will be interrupted.
r2.threadID{t2}
- Instance saved in resource r2
and observed by thread t2
. It will be printed by thread t2
if it will be interrupted.
r1.threadID{t2}
- Instance saved in resource r1
and observed by thread t2
in case, eg, if it calls (directly) r1.run()
.
r2.threadID{t2}
- Instance saved in resource r2
and observed by thread t1
in case, eg, if it calls (directly) r2.run()
.
It is unlikely that you need 3-rd and 4-th instances, so you may:
In that case you will have two instances : threadID{t1}
, which is observed by thread t1
, and threadID{t2}
, which is observed by thread t2
.
In that case you will have two instances : r1.threadID
, which is observed via r1
(by thread t1
), and r2.threadID
, which is observed via r2
(by thread t2
).
There is no inherent reason why a ThreadLocal
variable needs to be static. It's just that, the problem that ThreadLocal
solves is a problem that usually only occurs in programs that are based on static-y design ideas.
IMO, you're most likely to find ThreadLocal
in code that originally was single-threaded until somebody "upgraded" it to use multiple threads. Thread local comes in handy when a large body of code originally referred to some static variable, and now you need each thread that's running through the same body of code to have its own copy.
IMO, ThreadLocal
is a code smell---a sign of Bad Design. A well designed, multi-threaded program should not need it.
A ThreadLocal
doesn't need to be static
. Just like any other variable, it depends on your intention:
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
}
The quote you gave refers exactly to the third case listed above.
ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread
However, it might be perfectly reasonable in some situations to associate state with a thread per instance , in which case you would want to use a non-static
ThreadLocal
instead (fourth case).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.