(EXT) http://www.cnblogs.com/moongeek/p/7857794.html
ThreadLocal, which is a thread-local variable. It can bind a variable to a portal on a particular thread, so that each thread has a copy of the amount of change, and each thread is not affected by the same variables, and is a lightweight synchronization of shared resources.
The following is an instance of Threadlocal, where two tasks share the same variable, and both tasks set the variable to a thread-private variable, so that although both tasks "hold" the same variable, they each hold a copy of the variable. Therefore, when a thread modifies the variable, it does not affect the value of the variable in another process.
1 public class LocalTest1 implements Runnable {2//ThreadLocal is normally set to static. It's just a portal to set local variables for a thread, and multiple threads need only one entry 3 private static threadlocal<student> localstudent = new ThreadLocal () {4 Usually rewrite the initialization method, one will analyze the source time will explain why 5 @Override 6 public Student InitialValue () {7 return new Studen T (); 8} 9};10 private Student Student = null;12 @Override14 public void Run () {Strin G ThreadName = Thread.CurrentThread (). GetName (); System.out.println ("" "+ ThreadName +" ": Is running!"); Random ramdom = new Random (); 20//randomly generate a variable int = ramdom.nextint (+); Tem.out.println ("" "+ ThreadName +" ": Set Age to:" + age); 24//Get thread local variable, change attribute value Student stu = getstudent (); Stu.setage (age); System.out.println ("" "+ ThreadName +" ": The first time the age value was read:" + stu.getage ()); 29 30 try {TimeUnit.SECONDS.sleep (2); 32 } catch (Interruptedexception e) {e.printstacktrace ();}35 System.out.println ("" "+ ThreadName +" ": The second read of the age value is:" + stu.getage ()); PNs}38, Public Student getstudent () {Student = loc Alstudent.get (); 41 42//If you do not override the initialization method, you need to determine whether it is empty, and then manually assign a value of threadlocal to//if (student = = null) {44/// Student = new Student ();//Localstudent.set (student);//}47 return student;49 }50 public static void Main (string[] args) {LocalTest1 ll = new LocalTest1 (); Read (ll, "Thread 1"), t2 thread = new Thread (ll, "Thread 2"), T1.start (), T2.start (), 58}59}60 68 public class student{62 private int age;63 + public Student () {* * *}67 public Student (int. This.age = age;69}70 ()-Public int getage () {The return age;73-}74, public void setage (int Age) {THIS.AGE = age;77}78}
Operation Result:
"Thread 1": Is running! "Thread 2": Is running! "Thread 2": Set Age to:45 "Thread 1": Set Age to:25 "Thread 1": The first read of the age value is: 25 "Thread 2": The first read of the age value is: 45 "Thread 1 ": The second read of the age value is: 25" Thread 2 ": The second read of the age value is: 45
1, ThreadLocal source Analysis
There are many ways to ThreadLocal the source code, but there are only three exposed public interfaces:
Public threadlocal{public T get () {} public void set (T value) {} public void Remove () {}}
set(T value)
is the method of setting local variables, the source code is as follows:
1 public void Set (T value) {2 //Gets current thread 3 thread T = Thread.CurrentThread (); 4 //Gets Threadlocalmap reference for current thread, details See below 5 threadlocalmap map = getmap (t); 6 //If not empty, update the value of the local variable 7 if (map! = NULL) 8 map.set (this, value); 9
//if it is not the first time, first initialize the else11 createmap (t, value);
getMap(t)
The source code is as follows, each thread variable comes with a member variable of type Threadlocalmap, which holds the member variable of the thread.
1 Threadlocalmap getmap (thread t) {2 //Return the thread's member variable THREADLOCALS3 return t.threadlocals;4}
However, Thread defaults to setting Threadlocals to NULL, so the first time you use local variables, you need to initialize them first.
Threadlocal.threadlocalmap threadlocals = null;
ThreadLocalMap
is the inner class defined in the ThreadLocal
class, and its function is to store the thread's local variables. A ThreadLocalMap
reference to threadlocal is used as a key, with a local variable as the value, stored in ThreadLocalMap.Entry
(a data structure that stores the key value). About ThreadLocalMap
The source code, the following will be detailed introduction, here as long as the principle can be known.
Thus we can summarize ThreadLocal
the following design ideas:
ThreadLocal
It's just a portal that accesses local variables.
- The value of the local variable exists locally on the thread
Thread
class, which defaults to null, and is ThreadLocal
initialized only when accessed.
- [Threadlocalmap design ideas in the following introduction to the
ThreadLocalMap
source code will be analyzed]
get()
is to get thread local variables, the source code is as follows:
1 public T get () {2 //Get current thread 3 Thread T = Thread.CurrentThread (); 4 //Get a threadlocals variable for current thread 5 Thr Eadlocalmap map = getmap (t); 6 if (map! = null) {7 //If not NULL, the current threadlocal is the primary key to obtain the corresponding Entry 8 threadlocalmap.entry e = Map.getentry (this); 9< C8/>if (E! = null) { @SuppressWarnings ("unchecked") one- T result = (t) e.value;12 return result;13 } }15 //If the value is null, initialize the return Setinitialvalue (); 17}
Let's take a look at setInitialValue()
the operation of the initialization function:
1 private T Setinitialvalue () {2 //Get initial default value 3 t = InitialValue (); 4 //Get current thread 5 thread T = thread.cur Rentthread (); 6 //Get the thread's Threadlocalmap reference 7 threadlocalmap map = getmap (t); 8 //NOT NULL overwrite 9 if (map! = null) Map.set (this, value); else12 //If NULL, initialize with the key threadlocal variable, the default value of Createmap (t, value); 14}15 16/ /default initialization returns a null value, which is why you need to override the method. If there is no Override, the first get () operation obtains a thread-local variable of NULL, needs to be judged and manually called set () to initialize protected T InitialValue () { return null;19}
2, Threadlocalmap source Analysis
The thread class contains a member variable threadlocals of type Threadlocalmap, which is a data structure that stores thread local variables directly. ThreadLocal is just an entrance, through the ThreadLocal operation Threadlocals, the local variable check and change operation. That's why Threadlocal exposes three of public interfaces. Also, because the key in Threadlocalmap is the ThreadLocal class, you need to set up multiple ThreadLocal if you want to set multiple local variables for a thread. Below to analyze the threadlocalmap of the source code.
ThreadLocalMap
There are several core properties, similar to HashMap:
Table default size, size 2, for hash positioning private static final int initial_capacity = 16;//The array of key-value pairs, private entry[] table;//the critical value of the expansion, when T Able elements large to this value, will be expanded to private int threshold;
set(T)
when calling a method in Threadlocal, the Threadlocalmap method is called set(ThreadLocal, T)
,
1 private void Set (Threadlocal<?> key, Object value) {2 entry[] tab = table, 3 int len = tab.length; 4< c3/>//hash addressing, with table array length minus 1 (binary is all 1) and, so the array length must be 2 of the second side, reduce the likelihood of Hash repetition 5 int i = Key.threadlocalhashcode & (len-1); 6 7 //The subscript computed from the hash value starts traversing 8 for (Entry e = tab[i]; 9 E! = null;10 e = tab[i = Nextindex (i, Len)]) {11
//obtains the key of the entry threadlocal<?> k = E.get (); if the key and the same pass over, overwrite the original value, also indicates that A threadlocal variable can only hold a local variable for one thread if (k = = key) { E.value = value;16 return;17 }18 //key is empty, Then replace the node, if (k = = null) { replacestaleentry (key, value, i), return;22 }23 }24 25 Tab[i] = new Entry (key, value); + int sz = ++size;27 //Whether it is necessary to enlarge if (!cleansomeslots (i, SZ) && Amp SZ >= threshold) rehash ();
Why is it that the array length of 2 is advantageous for the hash calculation to not repeat? Let's take a look, obviously, and a binary is all 1 of the number, can guarantee the maximum number of bits of the original, so the repetition probability will become smaller.
It can be seen that Threadlocalmap uses linear detection and hashing to solve the problem of hash conflict. That is, if a hash of the array subscript is occupied, that is, the hash value is repeated, then on the basis of the subscript plus 1 test the next subscript, until a null value is found. For example, the hash calculates that the subscript i is 6,table[6] already has value, then try Table[7] is occupied, and so on, until a null value is found. The above is the method of saving thread local variables.
Then analyze the method in the Threadlocal get()
, which called the Threadlocalmap map.getEntry(this)
method, and the threadlocal as a parameter passed in, return an ThreadLocalMap.Entry
object (hereafter referred to as entry), the source code is as follows:
1 private Entry Getentry (threadlocal<?> key) {2 //hash computed array subscript 3 int i = key.threadlocalhashcode & (table . length-1); 4 //Get the Subscript node 5 Entry e = table[i]; 6 //If the node exists, and the key and the passed Threadlocal object is the same, the node is returned (indicating that the node does not have hash conflict processing) 7 if (E! = null && e.get () = = key) 8 return e; 9 //If the node does not meet the requirements directly, a hash conflict may be processed, then another processing of ten Else11 Return Getentryaftermiss (key, I, E); 12}
Again to analyze getEntryAfterMiss(ThreadLocal, int , Entry)
the source code:
1// if (e = = NULL | | E.get ()! = key) 2 private Entry Getentryaftermiss (threadlocal<?> key, int i, Entry e) {3< c1/>entry[] tab = table; 4 int len = tab.length; 5 //from the wash mark for I to start the traversal until the next empty node is encountered or the node that satisfies the requirement 6 while (E! = null) {7 threadlocal<?> k = E.get (); 8 if (k = = key) 9 return e;10 if (k = = null) one ///node is not empty, key is empty, the node is cleaned expungestaleentry (i); Else14 //I move back i = Nextindex (i, Len); e = tab[i];17 }18 //return null value returned null;20}
The above is threadlocalmap a few more critical source code analysis.
To sum up, ThreadLocal just accesses a thread local variable of a portal, is actually stored local variables in the thread local, while ThreadLocal also as a key to hash find the location of the variable. Perhaps you would like to, why not set the Threadlocalmap to < thread,variable> type, the Thread as the primary key, but to add an intermediate module threadlocal? My idea is that, as a result, this can really meet the demand, but it is not possible to hash lookup, if a thread of local variables too much, through a linear lookup will take a lot of time, using threadlocal as the middle key, you can hash lookup, and in fact, the addition of local variables, Find and delete need to do a lot of work, the designer's idea is to encapsulate these operations in a threadlocal class, and only exposed three commonly used interfaces, if the threadlocal removed, these operations may be written in the thread class, against the design of the "unitary" principle Sunline, we do this by taking a "name" for each local variable (that is, a threadlocal corresponds to a local variable), which is convenient to use.
Go The threadlocal source analysis of Java multithreading Learning