First, be clear: threadlocal is not a multithreaded class, or it should be called a thread-local variable. This can be seen from the JDK definition in threadlocal
public class Threadlocal<t>extends Object
It can be seen that threadlocal is just an ordinary class and does not inherit from thread or implement Runnable interface.
You can also see that Threadlocal uses generics so that he can manipulate almost any type of data. Here's what the JDK API code is all about.
For this class, look at some of the descriptions in the JDK API:
This class provides thread-local (thread-local) variables. These variables are different from their ordinary counterparts, because each thread that accesses a variable (through its Get or set method) has its own local variable, independent of the initialized copy of the variable. ThreadLocal instances are typically private static fields in a class that want to associate the state with a thread (for example, a user ID or transaction ID).
1, threadlocal is not a thread, but a local variable of the county
2. Threadlocal is usually used as a private static variable in the class.
3. Each thread has its own local variable, which does not conflict with each other and does not affect the operation of the variable value, there is no resource conflict.
In general, threadlocal as a threading tool, providing a way for each thread to store and access thread variables independently, so that the data stored between different threads does not affect each other (so there is no resource contention).
Here's how threadlocal is used as a threading tool to provide each thread with a local variable for storing and accessing threads.
Threadlocal provides the following APIs for accessing thread local variables:
T |
get() Returns the value in the current thread copy of this thread's local variable. |
protected T |
initialValue() Returns the initial value of the current thread for this thread's local variables. |
void |
remove() Removes the value of this thread's local variable. |
void |
set(T value) Sets the value in the current thread copy of this thread's local variable to the specified value. |
You can see that each is a generic type. The working principle of the interface is described in detail below.
A static inner class is also provided in the Threadlocal class:
Static Class Threadlocalmap
We can think of this threadlocalmap as an ordinary map type, which can be saved with a key-value pair, which is easy to understand.
This threadlocalmap is defined in threadlocal, but is used in the thread class Java.lang.Thread. The following definitions are in the thread class:
Threadlocal.threadlocalmap threadlocals = null
The implication is that the thread class has a variable of type threadlocal.threadlocalmap like map, which can be used to store the value of a key-value pair type.
The following is a simple example, based on the output results, analysis of thread and threadlocal working process.
Class Serialnum
public class Serialnum {//The next serial number to be assigned private static int nextserialnum = 0; public static ThreadLocal Serialnum = new ThreadLocal () { protected synchronized Object InitialValue () { return NE W Integer (nextserialnum++); } }; public static int Get () { return ((Integer) (Serialnum.get ())). Intvalue (); public static void Set (int val) { serialnum.set (val); }}
Class Serialnum defines a private static ThreadLocal type of anonymous inner class Serialnum variable, in fact, can be directly new ThreadLocal, so write just to implement overriding its InitialValue method, Because the InitialValue () method returns a null value in Threadlocal, it is necessary to note that the InitialValue () method is a lazy loading method that is called internally by the Threadlocal class. and is called only when get () of the first Threadlocal class is invoked, overriding it so that the local variable has an initial value.
Both the static get () and set () methods of the Serialnum class call the Get () and set () methods of the Threadlocal class.
Class: ThreadTest
public class ThreadTest extends thread{@Overridepublic void Run () {//TODO auto-generated method stub//First Print initial value SYSTEM.OUT.P Rintln (Thread.CurrentThread (). GetName () + ":" +serialnum.get ());//Current Value plus 4serialnum.set (Serialnum.get () +4);// The value after printing plus 4 System.out.println (Thread.CurrentThread (). GetName () + ":" +serialnum.get ()); public static void Main (string[] args) {//TODO auto-generated method Stubthreadtest t = new threadtest (); ThreadTest t2 = new ThreadTest (); threadtest t3 = new ThreadTest (); T.start (); T2.start (); T3.start ();}}
The static Get () and set () methods of the Serialnum class are called in the Run method in ThreadTest.
The output results are as follows:
Thread-2:2
thread-0:0
Thread-1:1
Thread-2:6
Thread-0:4
Thread-1:5
Let's start by analyzing why such a result occurs. We'll take the thread Thread-0, which corresponds to the thread that T.start () started.
1 . When the T thread runs first (thread-0), Serialnum.get () is called, and the threadlocal get method is called again. The Get () method for Threadlocal is as follows:
Public T get () { Thread T = Thread.CurrentThread (); Threadlocalmap map = getmap (t); if (map! = null) return (T) map.get (this); Maps is constructed lazily. If the map for this thread ///doesn ' t exist, create it, with this ThreadLocal and its //initial value as its onl Y entry. T value = InitialValue (); Createmap (t, value); return value; }
The Get () method first obtains the current thread, and then calls Getmap (), the API method is as follows:
Threadlocalmap Getmap (Thread t) { return t.threadlocals; }
Getmap () returns the Threadlocals variable in the current thread, as we said before, a variable of type threadlocal.threadlocalmap is defined in thread, which is it.
Then in the Get () method, check that map is not NULL, and if it is a null value, it will call InitialValue (). And this method is rewritten, it returns the current value of the static variable Nextserialnum defined in the Serialnum class, and then Nextserialnum+1. Because the Nextserialnum is initially 0, the return is 0. Then call Createmap (T,value). The API content is as follows:
void Createmap (Thread T, T firstvalue) { t.threadlocals = new Threadlocalmap (this, firstvalue); }
You can see that a Threadloadmap object was created in Createmap and copied to the Threadlocals variable of the current thread. The newly created Threadlocalmap class holds the value of the local variable, where the key is this, which is the private static ThreadLocal serialnum that we defined in the Serialnum class.
The last Get () method returns the initialized value 0.
While
The above is the reason why the first output of thead-0 prints out 0.
2 . When thread thread-0 runs to Serialnum.set (Serialnum.get () +4); This sentence when we see what's going on
First Serialnum.get () +4 takes out the value of the thread local variable saved in the threadlocal variable serialnum, looking back at the introduction of the Threadlocal.get () method, because the current thread already has Threadlocalmap Type of threadlocals, so the Map.get (this) is called directly, where this is still the private static ThreadLocal serialnum that we defined in the Serialnum class.
This returns the value in the map. Then call Threadlocal's set () method after +4. Let's look at the JDK contents of the Set () method:
public void Set (T value) { Thread T = Thread.CurrentThread (); Threadlocalmap map = getmap (t); if (map! = null) Map.set (this, value); else createmap (t, value); }
You can see that the set () method is the first to get the current thread and get the Threadlocalmap type map from the current thread. If map is not NULL, the value is saved in. If NULL, the new Threadlocalmap in Createmap, save the value, and assign the object of the Threadlocalmap type to the current thread's threadlocals variable ( See Createmap () method).
After running, the local variable value is equal to 0+4=4.
This is why the second printed value is Thread-0:4.
Let's talk about the second thread thread-1. The second thread starts, because the static variable nextserialnum is already 1 (after being read by the thread thread-0 + +). So he was starting from 1 to print. And the subsequent +4 operations do not conflict with thread thread-0 and thread-2. Because:
thread-0 The local variable of this thread is saved into Threadlocalmap, the THREADLOCALMAP variable is copied to the threadlocals variable of the thread (that is, thread-0 itself). Similarly, thread-1;thread-2 the local variables of the two threads are saved into the Threadlocalmap, they are copied to the threadlocals variable of the thread. So after the operation is from their own thread to take threadlocalmap, of course, do not affect each other. The same point is that the keys in the threadlocalmap of these three threads are the same Threadlocal object.
As you can see from this example, after the local variable is initialized, it's okay to start with that nextserialnum, which should be described in the JDK API: accessing a variable (via its get or set method), each thread has its own local variable, independent of the initialization copy of the variable
The above is their own threadlocal use of the discussion. Start to be afraid to say not clear, just want to write a straightforward point. Later, I felt a wordy.
On the understanding of Threadlocal class in Java