Threadlocal Introduction
When you use threadlocal to maintain variables, Threadlocal provides a separate copy of the variable for each thread that uses the variable, so each thread can independently change its own copy without affecting the 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.
There are only 4 methods of the Threadlocal class interface:
- void set (T value) sets the value of the thread local variable for the current thread.
- Public T Get () This method returns the thread local variable that corresponds to the current thread.
- The public void Remove () Removes the value of the current thread local variable to reduce memory usage, which is a new method of JDK 5.0. 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 T 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.
Threadlocal principle
Each thread has a separate copy of the Threadlocalmap, which stores the values that can only be read and modified by the current thread. The Threadlocal class implements the isolation of variable access in different threads by manipulating the threadlocalmap copies of each line thread, because each thread's variables are unique, and it's clear to look at the code.
/ * This is the definition of the thread class, which contains a local variable, threadlocals,threadlocal, by manipulating the local variable to implement the function of the * / Public classThreadImplementsRunnable {/*ThreadLocal values pertaining to this thread. This map was maintained by the ThreadLocal class. */Threadlocal.threadlocalmap threadlocals=NULL...}
/ * This is the Threadlocal implementation class, we mainly look at its Get/set method * / Public classThreadlocal<t> {/*** Returns the value in the current thread's copy of this * thread-local variable. If the variable have no value for the * current thread, it is first initialized to the value returned * by an invocation of The {@link#initialValue} method. * * @returnThe current thread ' s value of this thread-local*/ PublicT Get () {Thread T=Thread.CurrentThread (); Threadlocalmap Map=Getmap (t); / * Guess, it must be to get the local variable of the current thread class threadlocals*/ if(Map! =NULL) {threadlocalmap.entry e= Map.getentry ( This); if(E! =NULL) {@SuppressWarnings ("Unchecked") T result=(T) E.value; returnresult; } } returnsetinitialvalue ();}/*** Variant of Set () to establish initialvalue. Used instead * of set () in case user has overridden the set () method. * * @returnThe initial value*/PrivateT Setinitialvalue () {T value=InitialValue (); Thread T=Thread.CurrentThread (); Threadlocalmap Map=Getmap (t); if(Map! =NULL) Map.set ( This, value); ElseCreatemap (t, value); / * If Threadlocals does not exist, then new one, and put value in the * * returnvalue;}/*** Sets the current thread's copy of this thread-local variable * to the specified value. Most subclasses would have a no need to * override this method, and relying solely on the {@link#initialValue} * method to set the values of Thread-locals. * * @paramValue the value to is stored in the current thread's copy 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); / * If the threadlocal does not exist, just new one and set the value in the */}/*** Removes the current thread's value for this thread-local * variable. If this thread-local variable is subsequently * {@linkplain#get Read} by the current thread, its value would be * reinitialized by invoking it {@link#initialValue} method, * unless its value is {@linkplain#set Set} by the current thread * in the interim. This could result in multiple invocations of the * {@codeInitialValue} method in the current thread. * * @since1.5*/ Public voidRemove () {Threadlocalmap m=Getmap (Thread.CurrentThread ()); if(M! =NULL) M.remove ( This); }
void Createmap (Thread T, T firstvalue) {
T.threadlocals = new Threadlocalmap (this, firstvalue);
}
}
ThreadLocal vs Synchronized
in the synchronization mechanism, the lock mechanism of the object guarantees that only one thread accesses the variable at the same time, and multiple threads need to queue to access the variable, " change space with time ". At this time the variable is shared by multiple threads, using the synchronization mechanism requires the program to carefully analyze when to read and write variables, when to lock an object, when to release object locks and other complex problems, programming and writing is relatively difficult.
Threadlocal, however, solves multiple threads of concurrent access from another angle. Threadlocal provides a separate copy of the variable for each thread, isolating the access violation of multiple threads to the data. Because each thread has its own copy of the variable, there is no need to synchronize the variable. " space-for-time", "concurrent resources become no longer required to preempt".
Usage examples
All JDBC behavior includes that the transaction is controlled based on a connection object, and the method of obtaining connection requires good concurrency support. Otherwise, when a transaction commits and closes connection, another connection may be preparing to commit, which will inevitably lead to a failure.
/* This is a normal class to get the connection object, and the connection obtained with that class can be shared by multiple threads.
Public classconnectionholder{PrivateMap<datasource, connection> connectionmap =NewHashmap<datasource, connection>(); PublicConnection getconnection (DataSource DataSource)throwsSQLException {Connection Connection=Connectionmap.get (DataSource); if(Connection = =NULL||connection.isclosed ()) {Connection=datasource.getconnection (); Connectionmap.put (DataSource, connection); } returnconnection; } Public voidremoveconnection (DataSource DataSource) {connectionmap.remove (DataSource); }}/* takes the Threadlocal class and saves the above Connectionholder copy in the current thread so that each thread has its own connectionholder, there is no multithreading conflict problem * / Public classsinglethreadconnectionholder{Private StaticThreadlocal<connectionholder> Localconnectionholder =NewThreadlocal<connectionholder>(); Public StaticConnection getconnection (DataSource DataSource)throwsSQLException {returnGetconnectionholder (). getconnection (DataSource); } Public Static voidremoveconnection (DataSource DataSource) {Getconnectionholder (). Removeconnection (DataSource); } Private StaticConnectionholder Getconnectionholder () {Connectionholder Connectionholder=Localconnectionholder.get (); if(Connectionholder = =NULL) {Connectionholder=NewConnectionholder (); Localconnectionholder.set (Connectionholder); } returnConnectionholder; }}
Reference documents:
http://blog.csdn.net/lufeng20/article/details/24314381
Http://www.cnblogs.com/davenkin/archive/2013/02/23/java-tranaction-4.html
Threadlocal Study Record