In-depth study of java.lang.ThreadLocal class
I. Overview
What is threadlocal? In fact, Threadlocal is not a local implementation version of a thread, it is not a threaded, but a threadlocalvariable (thread local variable). Perhaps it would be more appropriate to name it Threadlocalvar. The thread local variable (ThreadLocal) function is very simple, that is, for each thread that uses the variable to provide a copy of the value of a variable, is a special thread binding mechanism in Java, is each thread can independently change their own copy, And does not conflict with other threads ' replicas.
From a thread's point of view, each thread maintains an implicit reference to a copy of its thread's local variables, as long as the thread is active and the ThreadLocal instance is accessible, and all copies of its thread's local instance are garbage collected after the threads have disappeared (unless there are other references to those replicas).
The data accessed through threadlocal is always related to the current thread, that is, the JVM binds the private local instance access space for each running thread, thus providing an isolation mechanism for concurrent access problems that often occur in multithreaded environments.
How does threadlocal maintain a copy of a variable for each thread? In fact, the idea of implementation is simple, there is a map in the Threadlocal class that stores a copy of each thread's variable.
To sum up, for the problem of multi-thread resource sharing, the synchronization mechanism adopts the way of "time-changing Space", and threadlocal adopts the way of "changing time by Space". The former provides only one copy of the variable, allowing different threads to queue access, and the latter provides a variable for each thread, so it can be accessed at the same time without affecting each other.
Second, API description
ThreadLocal ()
Creates a thread-local variable.
T get ()
Returns the value in the current thread copy of this thread's local variable, and if this is the first time a thread calls the method, creates and initializes the copy.
Protected T InitialValue ()
Returns the initial value of the current thread for this thread's local variables. This method is called at most once per access thread to get the local variable for each of the threads, that is, the first time the thread accesses the variable using the Get () method. If the thread calls the set (T) method before the Get method, then the InitialValue method is not called in the threads.
If the implementation returns only NULL, and if the programmer wants to initialize a thread-local variable to a value other than NULL, the subclass must be created for ThreadLocal and overridden by this method. Typically, anonymous inner classes are used. A typical implementation of InitialValue invokes an appropriate construction method and returns the newly constructed object.
void Remove ()
Removes the value of this thread's local variable. This may help reduce the storage requirements for thread-local variables. If you access this thread's local variable again, by default it will have its initialvalue.
void set (T value)
Sets the value in the current thread copy of this thread's local variable to the specified value. Many applications do not require this functionality, they rely only on the InitialValue () method to set the value of a thread-local variable.
The InitialValue method is generally overridden in a program to give a specific initial value.
Iii. Typical examples
1, Hiberante the Session tool class Hibernateutil
This class is the hibernate official document in the Hibernateutil class, used for session management.
public class Hibernateutil {
private static log log = Logfactory.getlog (Hibernateutil.class);
private static final sessionfactory sessionfactory; Define Sessionfactory
static {
try {
Create Sessionfactory from the default profile Hibernate.cfg.xml
Sessionfactory = new Configuration (). Configure (). Buildsessionfactory ();
} catch (Throwable ex) {
Log.error ("Initialize Sessionfactory failed! ", ex);
throw new Exceptionininitializererror (ex);
}
}
Create thread local variable session to save Hibernate session
public static final ThreadLocal session = new ThreadLocal ();
/**
* Gets the session in the current thread
* @return Session
* @throws hibernateexception
*/
public static Session Currentsession () throws Hibernateexception {
Session S = (session) Session.get ();
If the session is not open, a new session is opened
if (s = = null) {
s = sessionfactory.opensession ();
Session.set (s); Save the newly opened session to the thread local variable
}
return s;
}
public static void CloseSession () throws Hibernateexception {
Gets the thread local variable and casts it to the session type
Session S = (session) Session.get ();
Session.set (NULL);
if (s! = null)
S.close ();
}
}
In this class, because there is no InitialValue () method to override Threadlocal, the first time the thread local variable session is created, its initial value is null, when the first call to Currentsession (), The Get () of the thread local variable The method is also null. Therefore, the session is judged, if NULL, a new session is opened and saved to the thread local variable session, this step is very critical, this is also "public static final ThreadLocal session = new ThreadLocal () "The object created by the session can be cast to hibernate session object reason.
2. Another example
Create a bean that sets the bean properties through different thread objects, guaranteeing the independence of the individual thread bean objects.
/**
* Created by IntelliJ idea.
* User:leizhimin
* date:2007-11-23
* TIME:10:45:02
* Student
*/
public class Student {
private int age = 0; Age
public int getage () {
return this.age;
}
public void Setage (int.) {
This.age = age;
}
}
/**
* Created by IntelliJ idea.
* User:leizhimin
* date:2007-11-23
* time:10:53:33
* Multi-threaded test program
*/
public class Threadlocaldemo implements Runnable {
Create thread local variable studentlocal, which you will find to save student object later
Private final static ThreadLocal studentlocal = new ThreadLocal ();
public static void Main (string[] agrs) {
Threadlocaldemo td = New Threadlocaldemo ();
thread T1 = new Thread (TD, "a");
Thread t2 = new Thread (TD, "B");
T1.start ();
T2.start ();
}
public void Run () {
Accessstudent ();
}
/**
* Example Business method, used to test
*/
public void Accessstudent () {
Gets the name of the current thread
String currentthreadname = Thread.CurrentThread (). GetName ();
System.out.println (Currentthreadname + "is running!");
Generate a random number and print
Random random = new random ();
int age = Random.nextint (100);
SYSTEM.OUT.PRINTLN ("thread" + Currentthreadname + "set Age to:" + age);
Gets a student object and inserts the age of the random number into the object properties
Student Student = Getstudent ();
Student.setage (age);
SYSTEM.OUT.PRINTLN ("thread" + Currentthreadname + "First read is:" + student.getage ());
try {
Thread.Sleep (500);
}
catch (Interruptedexception ex) {
Ex.printstacktrace ();
}
SYSTEM.OUT.PRINTLN ("thread" + Currentthreadname + "second read" is: "+ student.getage ());
}
Protected Student getstudent () {
Get local thread variable and cast to student type
Student Student = (Student) studentlocal.get ();
The first time the thread executes this method, Studentlocal.get () must be null
if (student = = null) {
Creates a student object and saves it to the local thread variable studentlocal
Student = new Student ();
Studentlocal.set (student);
}
return student;
}
}
Operation Result:
A is running!
Thread A set age to:76
B is running!
Thread B Set Age to:27
Thread A first read age is:76
Thread B First read age is:27
Thread A second read age is:76
Thread B Second Read age is:27
You can see that a, B, two threads, age, print at different times the values are exactly the same. This program through the use of threadlocal, not only to achieve multi-threaded concurrency, to take into account the security of data.
Iv. Summary
Threadlocal mainly solves the problem that the data data in multi-threading is inconsistent with concurrency. Threadlocal provides a copy of the data that is accessed concurrently in each thread and runs the business through the access replica, which results in memory consumption, which greatly reduces the performance cost of thread synchronization and reduces the complexity of thread concurrency control.
Threadlocal cannot use atomic types, only object types. Threadlocal is much simpler to use than synchronized.
Both threadlocal and synchonized are used to solve multi-threaded concurrent access. But there is an essential difference between threadlocal and synchronized. Synchronized is the mechanism by which a lock is used so that a variable or block of code can be accessed by only one thread at a time. Instead, Threadlocal provides a copy of the variable for each thread, so that each thread accesses the same object at a certain time, isolating data sharing from multiple threads. Synchronized, in contrast, is used to gain data sharing when communicating between multiple threads.
Synchronized is used for data sharing between threads, while threadlocal is used for data isolation between threads.
Of course threadlocal is not a substitute for synchronized, they deal with different problem domains. Synchronized is used to implement synchronization mechanisms and is more complex than threadlocal.
V. General steps for the use of threadlocal
1. In a multithreaded class (such as the Threaddemo Class), create a Threadlocal object threadxxx, which is used to save the object xxx between threads that need to be treated in isolation.
2. In the Threaddemo class, create a Method getxxx () that gets the data to be quarantined, and in the method it is judged that if the Threadlocal object is null, a new () object should be created to isolate the access type and cast to the type to be applied.
3, in the Threaddemo class of the Run () method, through the GetXXX () method to obtain the data to be manipulated, so that each thread can be guaranteed to correspond to a data object, at any time the operation of this object.
Original address: http://lavasoft.blog.51cto.com/62575/51926/.