Threadlocal implementation principle, and use instances to solve the problem of no session or session was closed (1) loading in non-web projects of spring and hibernate )!

Source: Internet
Author: User

In JDK 1.2, java. Lang. threadlocal is provided. threadlocal is used to solve the local variable independence problem of multi-threaded programs...

 

To view the API, we can view the definition and method of threadlocal:

 

This class provides thread-local variables. These variables are different from their common counterparts, becauseGetOrSetEach thread has its own local variable, which is independent of the initialization copy of the variable.ThreadlocalAn instance is usually a Private Static Field in the class. They want to associate the state with a thread (for example, user ID or transaction ID.

For example, the following class generates a unique local identifier for each thread. The thread ID is called for the first time.Uniquethreadidgenerator. getcurrentthreadid ()And will not be changed in subsequent calls.

 

Constructor Summary
ThreadLocal()

Create a local variable of the thread.

Method Summary
 T get()

Returns the value of the local variable in the current thread copy.
protected  T initialValue()

Returns the "Initial Value" of the current thread for the local variable of this thread ".
 void remove()

Remove the value of the current thread of the local variable of this thread.
 void set(T value)

Set the value in the current thread copy of the local variable of this thread to the specified value.

 

Remove()

Remove the value of the current thread of the local variable of this thread to reduce memory usage. This method is newly added to JDK 5.0. It should be noted that when the thread ends, the local variables of the thread will be automatically reclaimed, so explicitly calling this method to clear the local variables of the thread is not a required operation, but it can speed up memory recovery.

 

Initialvalue()

Returns the initial value of the local variable of the thread. This method is a protected method, apparently designed to overwrite the subclass. This method is a delayed call method. It is executed only once when the thread calls get () or set (object) for 1st times. The default implementation in threadlocal directly returns a null value. If the generic object is integer, it can be defined internally and overwritten.Initialvalue()
Returns integer data, such as 0!

 

Threadlocal is not a so-called "local thread", but a local variable in the thread. It can be understood as: "local thread variable (thread local variable )"!

 

Thread Local variables are already used in many languages, not Java's original... many languages (such as ibm xl Fortran) provide thread local variables at the syntax level.

 

The implementation principle of threadlocal is roughly as follows:

 

Package CN. vicky; </P> <p> Import Java. util. collections; <br/> Import Java. util. hashmap; <br/> Import Java. util. map; </P> <p> public class realizethreadlocal {</P> <p> private Map <string, Object> map = collections. synchronizedmap (New hashmap <string, Object> (); </P> <p> Public void set (object Value) {<br/> map. put (thread. currentthread (). getname (), value); <br/>}</P> <p> Public object get () {<br/> string threadnam E = thread. currentthread (). getname (); <br/> Object o = map. Get (threadname); <br/> If (O = NULL &&! Map. containskey (threadname) {<br/> O = initialvalue (); <br/> map. put (threadname, O); <br/>}< br/> return O; <br/>}</P> <p> Public void remove () {<br/> map. remove (thread. currentthread (). getname (); <br/>}</P> <p> Public object initialvalue () {<br/> return NULL; <br/>}</P> <p >}< br/>

 

In jdk5.0, threadlocal supports generics, and the class name of this class has changed to threadlocal <t>. The implementation principle is roughly as follows:

 

Package CN. vicky; </P> <p> Import Java. util. collections; <br/> Import Java. util. hashmap; <br/> Import Java. util. map; </P> <p> public class realizethreadlocal2 <t >{</P> <p> private Map <long, T> map = collections. synchronizedmap (New hashmap <long, T> (); </P> <p> Public void set (T value) {<br/> map. put (thread. currentthread (). GETID (), value); <br/>}</P> <p> Public t get () {<br/> long threadid = thread. currentthread () . GETID (); <br/> T o = map. Get (threadid); <br/> If (O = NULL &&! Map. containskey (threadid) {<br/> O = initialvalue (); <br/> map. put (threadid, O); <br/>}< br/> return O; <br/>}</P> <p> Public void remove () {<br/> map. remove (thread. currentthread (). getname (); <br/>}</P> <p> Public t initialvalue () {<br/> return NULL; <br/>}< br/>

 

 

How to use:

 

Package CN. vicky; </P> <p> public class sequencenumber {</P> <p> // override the initialvalue () method of realizethreadlocal2 by using an anonymous internal class, specify the corresponding initial value based on the generic type <br/> Private Static realizethreadlocal2 <integer> seqnum = new realizethreadlocal2 <integer> () {<br/> @ override <br/> Public integer initialvalue () {<br/> return 0; <br/>}< br/> }; </P> <p> // obtain the next sequence value <br/> Public int getnextnum () {<br/> seqnum. set (seqnum. get () + 1); <br/> return seqnum. get (); <br/>}</P> <p> Public static void main (string [] ARGs) {<br/> sequencenumber Sn = new sequencenumber (); <br/> // three threads share the SN, each generating a serial number <br/> testthread TT1 = new testthread (SN ); <br/> testthread TT2 = new testthread (SN); <br/> testthread TT3 = new testthread (SN); <br/> thread T1 = new thread (TT1 ); <br/> thread t2 = new thread (TT2); <br/> thread T3 = new thread (TT3); <br/> t1.start (); <br/> t2.start (); <br/> t3.start (); <br/>}< br/>

 

Package CN. vicky; </P> <p> public class testthread implements runnable {<br/> private sequencenumber Sn; </P> <p> Public testthread (sequencenumber Sn) {<br/> This. sn = Sn; <br/>}</P> <p> Public void run () {<br/> // each thread generates three sequence values <br/> for (INT I = 0; I <3; I ++) {<br/> system. out. println ("thread [" + thread. currentthread (). getname () + "] Sn [" + Sn. getnextnum () + "]"); <br/>}< br/>

 

Print:

 

Thread [thread-0] Sn [1]
Thread [thread-0] Sn [2]
Thread [thread-0] Sn [3]
Thread [thread-2] Sn [1]
Thread [thread-2] Sn [2]
Thread [thread-2] Sn [3]
Thread [thread-1] Sn [1]
Thread [thread-1] Sn [2]
Thread [thread-1] Sn [3]

 

Testthread TT1 = new testthread (SN );
Testthread TT2 = new testthread (SN );
Testthread TT3 = new testthread (SN );

Output result information. Although the serial numbers generated by each thread share the same sequencenumber (SN) instance, they do not interfere with each other, instead, they generate independent serial numbers, because we provide separate copies for each thread through threadlocal!

 

 

 

Let's look at a simple example:

Package CN. vicky. chapt05;/***** @ author Vicky. H */public class threadlocaltest1 {/** implement different static variables for each thread **/Private Static threadlocal <string> val = new threadlocal <string> (); public static class thread1 extends thread {private string name; Public thread1 (string name) {This. name = Name;} public void run () {system. out. println (name + "Initial Value:" + val. get (); Val. set ("V [" + name + "]"); system. out. print Ln (name + "after setting value:" + val. get () ;}} public static class thread2 extends thread {private string name; Public thread2 (string name) {This. name = Name;} public void run () {system. out. println (name + "Initial Value:" + val. get (); Val. set ("V [" + name + "]"); system. out. println (name + "after setting:" + val. get () ;}} public static void main (string [] ARGs) {Val. set ("1"); system. out. println ("Set Value in the main program:" + val. get (); (n EW thread1 ("A1 ")). start (); (new thread1 ("")). start (); (new thread2 ("B1 ")). start () ;}// set the value in the main program: 1 // A1 Initial Value: NULL // A1 after setting the value: V [a1] // B1 initial value: null // initial value of a: NULL // value after setting a: V [a] // value after setting B1: V [B1] // summary // threadlocal is used to solve data inconsistency caused by concurrency in multithreading. // Threadlocal provides a copy of the data concurrently accessed by each thread and runs the business by accessing the copy. As a result, the memory is consumed, single greatly reduces the performance consumption caused by thread synchronization, and also reduces the complexity of thread concurrency control. // Threadlocal cannot use the atomic type, but can only use the object type. // Threadlocal is much easier to use than synchronized. // Threadlocal and synchonized are both used to solve multi-thread concurrent access. However, threadlocal is essentially different from synchronized. Synchronized uses the lock mechanism to allow a variable or code block to be accessed by only one thread at a time. Threadlocal provides a copy of the variable for each thread, so that each thread does not access the same object at a certain time, thus isolating multiple threads from sharing data. Synchronized, on the contrary, is used to obtain data sharing when multiple threads communicate. // Synchronized is used for data sharing between threads, while threadlocal is used for data isolation between threads. // Of course, threadlocal cannot replace synchronized. They process different problem domains. Synchronized is used to implement synchronization mechanism, which is more complex than threadlocal.}

 

Package CN. vicky. chapt05;/***** @ author Vicky. H */public class threadlocaltest2 {/** implement different static variables for each thread **/Private Static string val; public static class thread1 extends thread {private string name; public thread1 (string name) {This. name = Name;} public void run () {system. out. println (name + "Initial Value:" + val); val = "V [" + name + "]"; system. out. println (name + "set post value:" + val) ;}} public static class thread2 extends thread {private string name; Public thread2 (string name) {This. name = Name;} public void run () {system. out. println (name + "Initial Value:" + val); val = "V [" + name + "]"; system. out. println (name + "after setting value:" + val) ;}} public static void main (string [] ARGs) {val = "1"; system. out. println ("Set Value in the main program:" + val); (new thread1 ("A1 ")). start (); (new thread1 ("")). start (); (new thread2 ("B1 ")). start ();} // set the value in the main program: 1 // A1 Initial Value: 1 // A1 after setting the value: V [a1] // a initial value: V [a1] // value after setting a: V [a] // Initial Value of B1: V [a] // value after setting B1: V [B1]}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.