The demo source address used in this article: Https://github.com/mantuliu/javaAdvance the class lesson1threadlocal
This article is the first in the Java Progression Series, followed by the introduction of Java-related advanced applications and analysis. Personally, I have always been more advocating threadlocal design principles and implementation methods. The following is a description of threadlocal from Baidu Encyclopedia:
threadlocal is easy to words too literally, assuming it is a "local thread". In fact, threadlocal is not a thread, but a local variable of thread, perhaps naming it as threadlocalvariable is easier to understand.
Therefore, the code to write thread-local variables in Java is relatively clumsy, resulting in thread-local variables not being well-popularized in Java developers.
interface method for Threadlocal
Threadlocal class interface is very simple, there are only 4 methods, let us first look at:
void Set (Object value)
Public void Remove ()
removes the value of the current thread local variable to reduce memory usage, which is a new method of JDK 1.5. It is important to note that when the thread ends, the local variables of the thread that should be used are automatically garbage collected, so it is not necessary to explicitly call the method to clear the thread's local variables, but it can speed up the memory reclamation.
protected Object initialvalue ()
returns the initial value of the thread's local variable, which is a protected method, apparently designed for subclasses to overwrite. This method is a deferred call method that executes only when the thread calls get () or set (Object) for the 1th time, and executes only 1 times. The default implementation in Threadlocal returns a null directly.
It is worth mentioning that, in JDK5.0, Threadlocal already supports generics, and the class name of the class has become threadlocal<t>. The API methods are also adjusted accordingly, and the new version of the API method is void set (t value), t get (), and T InitialValue ().
How does threadlocal maintain a copy of a variable for each thread? In fact, the idea is simple: Define a threadlocalmap in the Threadlocal class, each thread has a variable of that type--threadlocals--is used to store a variable copy of each thread, the key of the element in the map is the thread object, The value corresponds to the variable copy of the thread.
Threadlocal emphasizes the storage, it is not a Java-specific concept, more precisely it should be called threadlocal storage, is a thread of local storage, in our work, we will encounter a scenario, a user in the service after a lot of operations, When we use log4j and logback to print logs, we want to be able to clearly mark all the actions of the same user in the log, at this time, our log system is actually using the threadlocal to implement this function, in the same thread to store and pass variables. The following code is an example of a threadlocal use:
Package com.mantu.advance;/** * Blog http://www.cnblogs.com/mantu/* GitHub https://github.com/mantuliu/* @author Mantu * */public class Lesson1threadlocal {public static threadlocal<string> local = new threadlocal<string> (); /declare static ThreadLocal variable public static threadlocal<string> Local2 = new threadlocal<string> ();// Declares a static threadlocal variable public static void main (String [] args) {for (int i=0;i<5;i++) {Testthread Testt Hread = new Testthread ();//create 5 threads new Thread (Testthread). Start (); }}}class Testthread implements runnable{@Override public void Run () {//TODO auto-generated met Hod stub try {thread.sleep (1l);//allow thread to pause for other threads to execute} catch (Interruptedexception e) { TODO auto-generated Catch block E.printstacktrace (); } Lesson1ThreadLocal.local.set (Thread.CurrentThread (). GetId () + ":" +system.currenttimemillis ()); Lesson1threadlocal. Local2.set (Thread.CurrentThread (). GetId () + ""); Firststep (); try {thread.sleep (1l);//allow thread to pause for other threads to execute} catch (Interruptedexception e) {//TODO Auto-gen Erated Catch block E.printstacktrace (); } secondstep (); try {thread.sleep (1l);//allow thread to pause for other threads to execute} catch (Interruptedexception e) {//TODO Auto-gen Erated Catch block E.printstacktrace (); } thirdstep (); try {thread.sleep (1l);//allow thread to pause for other threads to execute} catch (Interruptedexception e) {//TODO Auto-gen Erated Catch block E.printstacktrace (); } fourthstep (); try {thread.sleep (1l);//allow thread to pause for other threads to execute} catch (Interruptedexception e) {//TODO Auto-gen Erated Catch block E.printstacktrace (); } fstep (); } public void Firststep () {System.out.println (Lesson1ThreadLocal.local.get (). toStRing () + ": First step")//Get the threadlocal variable value of this thread and print} public void Secondstep () {System.out.println (Lesson1threadl Ocal.local.get (). toString () + ": Second Step"); } public void Thirdstep () {System.out.println (Lesson1ThreadLocal.local.get (). toString () + ": Third Step"); } public void Fourthstep () {System.out.println (Lesson1ThreadLocal.local.get (). toString () + ": Fourth Step"); } public void Fstep () {System.out.println (Lesson1ThreadLocal.local.get (). toString () + ": Fifth Step"); }}
The main idea of the code is 5 threads, using the same static threadlocal variable, each thread at startup, store the variables related to this thread, in the next 5 steps will be used to show that each thread used by the variables are independent, the results are as follows, You can perform your own execution and observe the results:
9:1470882533007:first step
11:1470882533023:first Step
10:1470882533024:first Step
13:1470882533024:first Step
9:1470882533007:second Step
12:1470882533024:first step
12:1470882533024:second step
13:1470882533024:second Step
11:1470882533023:second Step
10:1470882533024:second Step
11:1470882533023:third Step
10:1,470,882,533,024: Third Step
12:1470882533024:third step
9:1470882533007:fourth step
13:1470882533024:third Step
11:1470882533023:fourth Step
10:1470882533024:fourth Step
12:1,470,882,533,024: Fourth Step
13:1470882533024:fourth step
9:1470882533007:fifth step
12:1470882533024:fifth Step
10:1470882533024:fifth Step
13:1470882533024:fifth Step
11:1,470,882,533,023 : Fifth Step
The red part of the execution result shows that the thread ID of 9 is the same as the variable value from the threadlocal variable in the Step1 to STEP5 operation: 9 : 1470882533007, the threadlocal variable is used to realize the function of variable sharing within the same thread, and the operation of the same variable is isolated from other threads.
Here we begin to analyze the source code of Threadlocal, first from the set () method to look at:
Public void set (t value) { = thread.currentthread ();//gets to the current thread = getmap (t);// The current thread to obtain the corresponding storage mapifnull) map.set (this, value );//If map is not empty, the value is stored in map, the corresponding key is the current Threadlocal object else createmap (t, value);// If the map is empty, create a map and store the variable in the map }
Next, let's Analyze the Createmap () related code
void Createmap (Thread T, T firstvalue) { t.threadlocals = new Threadlocalmap (this, firstvalue);//Create THREADLOCALMAP, parameter is ThreadLocal variable and previously passed variable value } threadlocalmap (ThreadLocal firstkey, Object firstvalue) { table = new entry[ initial_capacity];//array of storage variables int i = Firstkey.threadlocalhashcode & (initial_capacity-1); Table[i] = new Entry (Firstkey, firstvalue);//stores the variable in an array of size = 1; Setthreshold (initial_capacity); }
Let's look at the source of Get ()
Public T get () { thread T = Thread.CurrentThread ();//The same gets the current thread threadlocalmap map = Getmap (T);// Because each thread has a separate map space, the thread gets to this map if (map! = null) { Threadlocalmap.entry e = Map.getentry (this);//through the key value, That is, our local variable to get to the actual variable value if (E! = null) return (T) e.value; } return Setinitialvalue (); }
From the source, we can find that each thread has a separate storage space, this space is a Map,map key value is the threadlocal variable we use, such as the threadlocal<string> local variable in the text, The value corresponding to this key is the variable thread.currentthread () that we store. GetId () + ":" +System.currenttimemillis (). The diagram below can help you understand the relationship between the threadlocal variable thread, the storage space map, the threadlocal variable, and the stored variables: a thread with only one storage space (map), and the map corresponds to multiple key-value pairs, Where the key is the threadlocal variable and the value is the actual variable used by the business.
Lesson1:threadlocal use demo and source code analysis