Java.lang class ThreadLocal<T>
We can call Threadlocal: thread-Local variables
The official API is described in this way:
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).
We can construct a Threadlocal object directly from new.
It has only 4 methods:
get() protected initialValue() 返回此线程局部变量的当前线程的“初始值”。 voidremove() 移除此线程局部变量当前线程的值。 voidsetvalue)
InitialValue This method is a deferred invocation method (which can be interpreted as a given initial value) and executes only 1 times when the thread calls get () or set (Object) for the 1th time. The default implementation in Threadlocal returns a null directly.
If the programmer wants a thread-local variable to have a value other than NULL, you must create a subclass for ThreadLocal and override this method. This operation is typically done using an anonymous inner class.
通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值 privatestaticnew ThreadLocal(){ publicinitialValue() { return0; } };
Threadlocal is doing this to maintain variables for each thread:
In the Threadlocal class, there is a Map<Thread,Object>, value that stores each thread and thread variable, the key of the element in the map is the thread object, and the value corresponds to the variable value of the thread.
We can write a simple implementation version of it ourselves:
Packagecn.Hncu;ImportJava.Util.HashMap;ImportJava.Util.Map; PublicClass Mythreadlocle {Private Map<Thread, Object> Map = NewHashMap<Thread, Object>(); PublicObject get () {ThreadCurthread= Thread.CurrentThread (); Object value= Map.Get (Curthread);returnValue } Public void Set(Object obj) {ThreadCurthread= Thread.CurrentThread ();Map.Put (curthread, obj); }}
Now let's use an example to deepen our understanding of threadlocal:
Package Cn.hncu;import Java.util.random;import org.junit.Test; Public classThreadlocaldemo {Private Staticthreadlocal<object> T1 =NewThreadlocal<object> (); Public StaticObjectGetValue() {Object o = t1.Get();//Do not give key, because T1 internally will automatically get the thread object of the current threads, and the above as a key into its pool to fetch obj if(o==NULL) {System. out. println ("Empty"); Random r =NewRandom (); o = R.nextint ( +); T1.Set(o); }returnO } @Test Public void Test() {Object obj = GetValue (); Object obj2 = GetValue ();//second time to get it, it's not empty.System. out. println (obj+","+OBJ2); System. out. println (OBJ==OBJ2);//trueA A =NewA (); Object obj3 = A.getvalue (); System. out. println (OBJ==OBJ3);//trueb b =NewB (); Final Object obj4 = B.getvalue (); System. out. println (OBJ3==OBJ4);//true //By the above example, as long as it is the same thread, regardless of the class, the Get object from Threadlocal is the sameSystem. out. println ("---to a different thread = = = =---");NewThread () {@Override Public void Run() {A A =NewA (); Object obj5 = A.getvalue (); System. out. println ("Obj5:"+OBJ5); b b =NewB (); Object obj6 = B.getvalue (); System. out. println ("Obj6:"+OBJ6); System. out. println ("Obj5=obj6:"+ (OBJ5==OBJ6)); System. out. println ("Obj4=obj5:"+ (OBJ4==OBJ5)); }}.start (); }}class a{ PublicObjectGetValue() {Object obj = Threadlocaldemo.getvalue (); System. out. println ("A:"+obj);returnObj }}class b{ PublicObjectGetValue() {Object obj = Threadlocaldemo.getvalue (); System. out. println ("B:"+obj);returnObj }}
From the above example we can know:
Different objects are accessed in each thread.
The reference to this newly created object is saved to a map of each thread by Threadlocal.set (), each thread has a map that executes Threadlocal.get (), and each thread pulls the object from its own map and So the objects in their own thread are taken out, and the threadlocal instance is used as the key to the map.
Look at the jdk1.7 part of the Threadlocal class source code:
Get () and set () methods:
/** * Returns theValueinch theCurrent thread ' sCopy ofThis * thread-LocalVariable. If theVariable has no value for the* Current Thread,it is FirstInitialized to theValue returned * byAn invocation of the{@link#initialValue} method.* * @return theCurrent thread ' s value ofThis thread-Local*/public TGet() {Thread t = thread.currentthread (); Threadlocalmap map = getmap (t);if(map! = null) {Threadlocalmap.entry E = map.getentry (this);if(E! = null)return(T) E.value; }returnSetinitialvalue (); }/** * Sets theCurrent thread ' sCopy ofThis thread-LocalVariable * to theSpecified value. Most subclasses would have no need to* Override this method, relying solely on the{@link#initialValue}* Method to Set theValues ofThread-locals. * * @param value theValue tobe storedinch theCurrent thread ' sCopy of* This thread-Local. */public voidSet(T value) {Thread T = thread.currentthread (); Threadlocalmap map = getmap (t);if(map! = null) map.Set(this, value);ElseCreatemap (t, value); }
Java---threadlocal usage and understanding implementation