I. Description of Threadlocal class
ThreadLocal, it is easy to let people words too literally, literal translation "local thread". Threadlocal is not a thread, it is a local variable of thread. When you use threadlocal to maintain a variable, it provides a separate thread copy for each thread that uses it, and each thread can change its own copy without affecting the corresponding copy of the other thread.
From the thread's point of view, the target variable is like a thread's local variable, which is the meaning of the "local" in the class name.
Ii. Common methods of threadlocal
①, the initial value of the current variable
Protected T InitialValue ()
The source code is as follows, this method is a protected method, obviously is designed to let subclass cover. The method is called at Get|set and will only be transferred once. Threadlocal default implementation returns null directly
protected T InitialValue () { returnnull; }
②, sets the thread local variable value of the current thread
void set (T value)
③, returns the thread local variable value of the current thread
Public T Get ()
④, deletes the thread local variable value of the current thread, saving memory footprint.
public void Remove ()
Thirdly, let's take a concrete example to see the specific usage of threadlocal---ID generator
ID Generator
Public InterfaceSequence { Public intgetId ();} Public classLocalsequenceimplImplementsSequence {Privatethreadlocal<integer> container =NewThreadlocal<integer>() {@OverrideprotectedInteger InitialValue () {return0; }; }; @Override Public intgetId () {Container.set (Container.get ()+ 1); returnContainer.get (); }}
Thread
Public classThreadlocaldemoextendsThread {Private StaticSequence obj; @SuppressWarnings ("Static-access") PublicThreadlocaldemo (Sequence obj) { This. obj =obj; } Public voidrun () { for(inti = 0; I < 3; i++) {System.out.println (Thread.CurrentThread (). GetName ()+ " : " +Obj.getid ()); } } Public Static voidMain (string[] args) {Sequence obj=NewLocalsequenceimpl (); Test (obj); } Static voidTest (Sequence obj) {threadlocaldemo thread1=NewThreadlocaldemo (obj); Threadlocaldemo thread2=NewThreadlocaldemo (obj); Threadlocaldemo thread3=NewThreadlocaldemo (obj); Thread1.start (); Thread2.start (); Thread3.start (); }}
Results:
Thread-0:1 thread-1:1thread-1:2thread-2:1thread-2:2thread-2:3thread
-1:3Thread-0:2thread-0:3
From the above results, each thread will only change its own local variables, and there is no case of interference with each other. As you can see, Threadlocal provides a separate copy of the thread that uses it.
Don't believe me? Let's verify below by one without using threadlocal.
Public class Implements Sequence { privatestaticint id = 0; @Override publicint getId () { = id + 1; return ID;} }
Results
Thread-0:2thread-0:4thread-0:5 thread-2:3thread-2:6thread-2:7thread-1:1thread-1:8thread -1:9
Looking closely at the result, three threads simultaneously access a local variable ID, which interferes with each other.
Iv. expansion
Look at the threadlocal source code, the bottom is to use map to achieve. We can design a threadlocal ourselves.
Public classMythreadlocal<t> { PrivateMap<thread, t> container = Collections.synchronizedmap (NewHashmap<>()); Public voidset (T value) {container.put (Thread.CurrentThread (), value); } PublicT Get () {Thread CurrentThread=Thread.CurrentThread (); T value=Container.get (Thread.CurrentThread ()); if(Value = =NULL&&!Container.containskey (CurrentThread)) {Value=InitialValue (); Container.put (Thread.CurrentThread (), value); } returnvalue; } protectedT InitialValue () {return NULL; }}
Brief analysis of ThreadLocal