Original address: http://www.ahlinux.com/java/20332.html
In concurrent programming, one important content is data sharing. When you create a thread that implements the Runnable interface and then turn on various thread objects that use the same runnable instance, all the threads share the properties defined in the Runnable object. That is, when you change any property in one thread, all threads are affected, and you see the first thread's modified value. Sometimes we want to, for example: multiple threads increase or decrease the same counter variable; however, sometimes we want to make sure that each thread can only work on a copy of its own thread instance without affecting the data of other threads.
The time to use threadlocal
For example, imagine that you are developing an e-commerce application that you need to process a customer request for each controller, generate a unique transaction ID, and upload it to the manager or DAO's business method for logging. One scenario is to pass the transaction ID as a parameter to all business methods. But this is not a good solution, it will make the code redundant.
You can use variables of type threadlocal to solve this problem. First generate a transaction ID in the controller or any preprocessor interceptor, then set the transaction ID in Threadlocal, and finally, whatever method the controller calls, it can get the transaction ID from threadlocal. And the controller of this application can handle multiple requests at the same time, at the framework level, because each request is processed in a separate thread, the transaction ID is unique to each thread and can be obtained from the execution path of all threads.
Extended reading: Sharing contextual data with Jax-rs Resteasyproviderfactory (threadlocalstack instance)
Threadlocal class
The Java Concurrency API provides a simple and efficient mechanism for using local thread variables in the Threadlocal class.
public class Threadlocal<t> extends Object {...}
This class provides a local thread variable. These variables are different from the regular variables they correspond to, and for regular variables, each thread can only access (through the Get or set method) its own, independent initialization of the variable copy. In a class, an instance of the Threadlocal type is a typical private, static (private static) field, because we can use it as a thread's association state (for example: User ID or transaction ID)
This class has the following methods:
- Get (): Returns the value of the local thread variable copied by the current thread.
- InitialValue (): Returns the initial value given to the local thread variable by the current thread.
- Remove (): Removes the value of the local thread variable assigned to the current thread.
- Set (T value): Sets a specific value for the local thread variable copied by the current thread.
How to use threadlocal?
The following example uses two local thread variables, namely ThreadID and StartDate. They all follow the recommended definition method, which is a field of the "private static" type. The ThreadID is used to distinguish between currently running threads, and startdate is used to get the time the thread was opened. The information above will be printed to the console to verify that each thread manages his own copy of the variable.
Class Demotask implements Runnable {//Atomic integer containing the next thread ID to be assigned private static final Atomicinteger NextID = new Atomicinteger (0); Thread local variable containing each thread ' s ID private static final threadlocal<integer> threadId = new Threadlocal<integer> () {@Override protected Integer InitialValue () {return nextid.getandinc Rement (); } }; Returns the current thread's unique ID, assigning it if necessary public int GetThreadId () {return threadid.get (); }//Returns the current thread ' s starting timestamp private static final threadlocal<date> StartDate = new Threadlocal<date> () {protected Date InitialValue () {return new date (); } }; @Override public void Run () {System.out.printf ("Starting Thread:%s:%sn", GetThreadId (), startdate.g ET ()); try {TimeUnit.SECONDS.sleep (int) math.rint (math.random () * 10)); } catch (Interruptedexception e) {e.printstacktrace (); } System.out.printf ("Thread finished:%s:%sn", GetThreadId (), Startdate.get ()); }}
It is now time to verify that the variable is inherently able to maintain its own state, regardless of the multiple initialization of multithreading. We first need to create the three threads that perform this task, then turn on the threads, and then verify the information they print to the console.
Starting thread:0: Wed Dec 15:04:40 ist 2014Thread finished:0: Wed Dec 15:04:40 ist 2014Starting thread:1: Wed Dec 15:04:42 ist 2014Thread finished:1: Wed Dec 15:04:42 ist 2014Starting thread:2: Wed Dec 15:04:44 ist 201 4Thread finished:2: Wed Dec 15:04:44 IST 2014
In the above output, the printed declaration sequence changes every time. I have put them in the sequence so that for each instance of the thread, we can clearly discern that the local thread variables remain in a secure state and are never confused. Try it yourself!
Local threading is typically used in situations where you have objects that do not satisfy thread safety, but you want to avoid the synchronous access that occurs when you use the Synchronized keyword and block, so that each thread has its own instance of the object.
Note: Local variables are a good alternative to synchronous or local threading, and it is always possible to keep threads safe. The only thing that might limit what you do is your app design constraints.
Warning: On a webapp server, a thread pool may be maintained, then the threadlocal variable will be removed before responding to the client, because the current thread may be reused by the next request. Furthermore, if you do not clean up after use, any reference to the class that it maintains-this class is loaded as part of the deployment application-will remain in the permanent stack and never be reclaimed by the garbage collection mechanism.
An article to help understand threadlocal in Java