First look at how Threadloacl does the shared variable implementation as a thread-private variable
Thread source inside, there is a threadloaclmap
null;
Threadloacl Set method source code
Public void set (T value) {
//Get current thread = Thread.CurrentThread ();
//Get current thread Threadloaclmap = Getmap (t); if NULL ) Map.set (this, value); Else createmap (t, value); }
Threadloacl Getmap method source code
threadlocalmap getmap (Thread t) { return t.threadlocals; }
Test treadlocal Thread Private
Public classA {Static FinalThreadlocal<string> Threadparam =NewThreadlocal<>(); Public Static voidMain (string[] args)throwsinterruptedexception {//a dead loop, a few more times to see the results. while(true) { //Thread 1 NewThread (() { //Setting ParametersThreadparam.set ("abc")); //Output ParametersSystem.out.println ("T1:" +threadparam.get ()); //looks like an extra operation .//Threadparam.remove ();}). Start (); TimeUnit.SECONDS.sleep (1); NewThread (() { //thread Two, test if you can get ABCSystem.out.println ("T2:" +threadparam.get ()); }). Start (); } }}
Test results
Thread 1 Output ABC forever
Thread 2 always outputs null
It looks nice. But there are places to watch out for.
If the thread pool is used, the following threads are passed to the thread pool for processing
/** * * @authorZhenweilai **/ Public classB {Static FinalThreadlocal<string> Threadparam =NewThreadlocal<>(); Public Static voidMain (string[] args)throwsinterruptedexception {//only 3 threads exist in the fixed poolExecutorservice Execservice = Executors.newfixedthreadpool (3); //A few cycles of death to see the effect . while(true) {Thread T=NewThread ((){Threadparam.set ("ABC"); System.out.println ("T1:" +threadparam.get ()); //If you do not call remove, the issue is raised//Threadparam.remove (); }); Execservice.execute (t); TimeUnit.SECONDS.sleep (1); Thread T2=NewThread ((){System.out.println ("T2:" +threadparam.get ()); }); Execservice.execute (T2); } }}
Test results:
T1:abc
T1:abc
T2:null
T2:ABC//problems caused by multiplexing threads
T1:abc
Cause: The thread pool submits threads to the queue, and when called, the thread is reused if there are idle threads, simply invoking the user-submitted Run method.
So when the threadlocal parameter is used, remember to call the Remove method
In addition to Threadlocal and inheritablethreadlocal, a child thread can share the parent thread's inheritablethreadlocal
Inheritablethreadlocal implementation of the key source
// when a thread is initialized, gets the current thread, as the parent thread Thread parent = CurrentThread (); // ifnull) this. Inheritablethreadlocals= Threadlocal.createinheritedmap (parent.inheritablethreadlocals);
Test code
/** * * @authorZhenweilai **/ Public classA {Static FinalInheritablethreadlocal<string> Threadparam =NewInheritablethreadlocal<>(); Public Static voidMain (string[] args)throwsinterruptedexception {//a dead loop, a few more times to see the results. while(true) { //thread 1, test if you can get parent thread parameters NewThread (() { //Setting ParametersThreadparam.set ("abc")); //Output ParametersSystem.out.println ("T1:" +threadparam.get ()); //thread 2, test if you can get thread 1 parameters NewThread ((){System.out.println ("T2:" +threadparam.get ()); //in order to test the line Cheng can be obtained, here first not delete//Threadparam.remove ();}). Start (); }). Start (); TimeUnit.SECONDS.sleep (1); //thread 3, test if you can get thread 1 parameters NewThread ((){System.out.println ("T3:" +threadparam.get ()); }). Start (); } }}
Output: The parameter can be obtained from the thread, not from the thread.
T1:abc
T2:abc
T1:abc
T3:null
T2:abc
T3:null
T1:abc
T2:abc
T3:null
T1:abc
T2:abc
Once again it looks beautiful, write a complex point below, and give it to the thread pool to execute
PackageThread.base.threadloacl;ImportJava.util.concurrent.ExecutorService;Importjava.util.concurrent.Executors;ImportJava.util.concurrent.TimeUnit;/** * * @authorZhenweilai **/ Public classB {Static FinalInheritablethreadlocal<string> Threadparam =NewInheritablethreadlocal<>(); Public Static voidMain (string[] args)throwsinterruptedexception {//only 3 threads exist in the fixed poolExecutorservice Execservice = Executors.newfixedthreadpool (3); //A few cycles of death to see the effect . while(true) { //thread 1, with two sub-threads insideThread T =NewThread ((){Threadparam.set ("ABC"); System.out.println ("T1:" +threadparam.get ()); Thread T2=NewThread ((){System.out.println ("T2:" +threadparam.get ());//Threadparam.remove (); }); Execservice.execute (T2); Thread T3=NewThread ((){System.out.println ("T3:" +threadparam.get ());//Threadparam.remove (); }); Execservice.execute (T3); }); Execservice.execute (t); TimeUnit.SECONDS.sleep (1); //thread 4, thread 1 siblingThread T4 =NewThread ((){Threadparam.set ("CBA"); System.out.println ("T4:" +threadparam.get ()); }); Execservice.execute (T4); } }}
Output Result:
T1:abc
T2:abc
T3:abc
T4:cba
T1:abc
T2:abc
T3:abc
T4:cba
T1:abc
T2:abc
T3:CBA//problems caused by multiplexing threads
T4:cba
Runnable is just a threading method, thread is the threading, need to add a shell to runnable, call start to use thread execution.
The thread pool only survives 3 threads, so when the thread (shell) is Cheng online, the shell's properties are reset only when they are created (for example, inheritablethreadlocal,threadlocal).
These shells were created and then submitted to the thread pool, but the threading method was not executed immediately, and the properties were modified by the other shells. When this threading method starts executing, it's not the shell you created.
Here thread 3, because thread switching uses the properties of the shell after being modified by thread 4.
Increasing the thread pool to satisfy each threading method using one thread independently can resolve the above problem. But who can predict how many threads will be executed at the same time?
Threadloacl,inheritablethreadlocal, principles, and some pits used in conjunction with thread pooling