Deep parsing of the role and usage of threadlocal threading classes in Java _java

Source: Internet
Author: User
Tags java web

The threadlocal differs from the thread member variable, threadlocal This class provides a thread-local variable. This local variable is not the same as the general member variable, threadlocal variables are used by multiple threads, each thread can only get a copy of the variable, which is described in the Java API, through the Reading API source code, found not a copy, what concept of replica? A clone? Or something else, too vague.

To be exact, the registry (map<thread,t>) of the threadlocal type of variable has changed, but the threadlocal type of the variable itself is indeed one, which is the essence!

Here's an example:

One, standard example

Define the Mythreadlocal class, create one of its object TLT, respectively, to four threads, the result of four threads TLT variable does not appear a common phenomenon, the second is the use of each, which means that four threads use a copy of the TLT (clones).

 
/** 
* uses the Threadlocal class 
/Public 
class Mythreadlocal { 
    //defines a threadlocal variable to hold int or integer data 
    Private threadlocal<integer> TL = new threadlocal<integer> () { 
        @Override 
        protected Integer InitialValue () {return 
            0; 
        } 
    }; 

    Public Integer Getnextnum () { 
        ///The TL value is fetched after 1, and the value of the set T1 is updated 
        tl.set (tl.get () + 1); 
        return Tl.get (); 
    } 



/** 
* Test thread 
/public class Testthread extends thread { 
    private mythreadlocal TLT = new mythreadlocal (); 
   public Testthread (mythreadlocal tlt) { 
        this.tlt = TLT; 
    } 

    @Override public 
    Void Run () {A for 
        (int i = 0; i < 3; i++) { 
            System.out.println (thread.currentthread) Name () + "\ T" + tlt.getnextnum ());}} 



/** 
* threadlocal test 
/public class Test {public 
    static void Main (string[] args) { 
        Mythreadlocal TLT = new mythreadlocal (); 
        Thread T1 = new Testthread (TLT); 
        Thread t2 = new Testthread (TLT); 
        Thread t3 = new Testthread (TLT); 
        Thread T4 = new Testthread (TLT); 
        T1.start (); 
        T2.start (); 
        T3.start (); 
        T4.start (); 

    } 



As you can see, three threads are independently numbered and do not affect each other:

Thread-0 1 
Thread-1 1 
Thread-0 2 
Thread-1 2 
Thread-0 3 
Thread-1 3 
Thread-2 1 
Thread-3 1 
Thread-2 2 
Thread-3 2 
Thread-2 3 
Thread-3 3 


Process finished with exit code 0


The Tlt object is a, nonsense TL object is also one, because the combinatorial relationship is one-to-one. However, the map within the TL object will create many integer objects as the threads increase. just integers and int are already universal. So the object attribute of the integer is not felt.

second, do not threadlocal

If you don't need to threadlocal, just redefine the Mythreadlocal class to:

 
  
/** 
* uses the Threadlocal class * 
/public class Mythreadlocal { 
    private Integer t1 = 0; 
    Public Integer Getnextnum () {return 
        t1=t1+1; 
    }    defines a ThreadLocal variable that is used to hold int or Integer data 
//    private threadlocal<integer> tl = new ThreadLocal <Integer> () { 
//        @Override 
//        protected Integer InitialValue () { 
//return            0; 
//        } 
//    }; 
//Public    Integer Getnextnum () {///// 
Take the value of TL to        add 1 and update set T1 value 
//        Tl.set (Tl.get () + 1) ; 
return        tl.get (); 
//    } 
}


Then run the test:

Thread-2 1 
Thread-2 2 
Thread-1 4 
Thread-1 6 
Thread-3 3 
Thread-3 9 
Thread-3 
Thread-1 8 
Thread-0 7 
Thread-0 
Thread-0 
Thread-2 5 

Process finished with exit code 0

 
From here, four threads share the TLT variable, and each thread modifies the TLT property directly.
 
Three, implement a threadlocal yourself
 

Package com.lavasoft.test2; 
Import java.util.Collections; 
Import Java.util.HashMap; 

Import Java.util.Map; /** * uses the Threadlocal class/public class Mythreadlocal {//defines a threadlocal variable to hold int or integer data private com.la 
        vasoft.test2.threadlocal<integer> tl = new com.lavasoft.test2.threadlocal<integer> () {@Override 
        Protected Integer InitialValue () {return 0; 

    } 
    }; 
        Public Integer Getnextnum () {///The TL value is fetched after 1, and the value of the set T1 is updated Tl.set (Tl.get () + 1); 
    return Tl.get (); } class Threadlocal<t> {Private Map<thread, t> Map = Collections.synchronizedmap (New hashmap<thr 

    EAD, t> ()); 
    Public ThreadLocal () {} protected T InitialValue () {return null; 
        Public T get () {Thread t = thread.currentthread (); 
        T obj = map.get (t); 
   if (obj = = null &&!map.containskey (t)) {obj = InitialValue ();         Map.put (t, obj); 
    return obj; 
    public void Set (T value) {map.put (Thread.CurrentThread (), value); 
    public void Remove () {Map.Remove (Thread.CurrentThread ());

 } 
}


To run the test:

Thread-0 1 
Thread-0 2 
Thread-0 3 
Thread-2 1 
Thread-2 2 
Thread-3 1 
Thread-2 3 
Thread-3 2 
Thread-1 1 
Thread-3 3 
Thread-1 2 
Thread-1 3 

Process finished with exit code 0


Surprisingly, this cottage version of the threadlocal also run very well, to achieve the JAVAAPI in the Threadlocal function.

Seeing the essence through phenomena

In fact, from a procedural point of view, the TLT variable is indeed a, no doubt. But why do the numbers printed out do not affect each other?
Is it because the integer is used? -----not.
The reason is: protected T initialvalue () and get (), because each thread is created when the map is not present when it is called. When it is invoked, a new variable is created with the type T. Each time a new, of course, each with a separate influence.
To see the essence, replace the integer and rewrite some of the classes:

Package com.lavasoft.test2; 
Import java.util.Collections; 
Import Java.util.HashMap; 

Import Java.util.Map; /** * uses the Threadlocal class/public class Mythreadlocal {//defines a threadlocal variable to hold int or integer data//Private threadlocal<bean> tl = new threadlocal<bean> () {private com.lavasoft.test2.threadlocal<bean> TL = 
            New Com.lavasoft.test2.threadlocal<bean> () {@Override protected Bean InitialValue () { 
        return new Bean (); 

    } 
    }; 
                @Override public String toString () {return "mythreadlocal{" + "tl=" + TL + 
    '}'; 
    Public Beans Getbean () {return tl.get (); } class Threadlocal<t> {Private Map<thread, t> Map = Collections.synchronizedmap (New hashmap<th 

    Read, t> ()); 
    Public ThreadLocal () {} protected T InitialValue () {return null; Public T get () {Thread T = Thread.CurrentThread (); 
        T obj = map.get (t); 
            if (obj = = null &&!map.containskey (t)) {obj = InitialValue (); 
        Map.put (t, obj); 
    return obj; 
    public void Set (T value) {map.put (Thread.CurrentThread (), value); 
    public void Remove () {Map.Remove (Thread.CurrentThread ());

 } 
}


Package com.lavasoft.test2; 

/** 
* Test Bean 
* 
/public class Bean { 
    private String id = "0"; 
    Private String name = "None"; 

    Public beans () { 
    } public 

    bean (string ID, string name) { 
        this.id = ID; 
        this.name = name; 

    Public String GetId () {return 
        ID; 
    } 

    public void SetId (String id) { 
        this.id = ID; 
    } 

    Public String GetName () {return 
        name; 
    } 

    public void SetName (String name) { 
        this.name = name; 
    } 

    Public String Showinfo () {return 
        "bean{" + 
                "id=" + ID + ' \ ' + 
                ", name= '" + name + ' \ ' + 
                '} '; 
    } 
}


Package com.lavasoft.test2; 

/** 
* Test thread 
/public class Testthread extends thread { 
    private mythreadlocal TLT = new mythreadlocal (); 
   public Testthread (mythreadlocal tlt) { 
        this.tlt = TLT; 
    } 

    @Override public 
    Void Run () { 
        System.out.println (">>>>>:" + TLT); 
        for (int i = 0; i < 3 i++) { 
            System.out.println (Thread.CurrentThread (). GetName () + "T" +tlt.getbean () + "T" +tlt.g Etbean (). Showinfo ());}}} 



Then run the test:

&GT;&GT;&GT;&GT;&GT;:MYTHREADLOCAL{TL=COM.LAVASOFT.TEST2.MYTHREADLOCAL$1@1DE3F2D} >>>>>: MYTHREADLOCAL{TL=COM.LAVASOFT.TEST2.MYTHREADLOCAL$1@1DE3F2D} >>>>>:mythreadlocal{tl= COM.LAVASOFT.TEST2.MYTHREADLOCAL$1@1DE3F2D} >>>>>:mythreadlocal{tl= 
COM.LAVASOFT.TEST2.MYTHREADLOCAL$1@1DE3F2D} Thread-1 com.lavasoft.test2.bean@291aff bean{id= ' 0 ', name= ' none '} Thread-2 com.lavasoft.test2.bean@fe64b9 bean{id= ' 0 ', name= ' none '} Thread-3 com.lavasoft.test2.bean@186db54 ' 0 ', name= ' none '} Thread-2 com.lavasoft.test2.bean@fe64b9 bean{id= ' 0 ', name= ' none '} Thread-2 com.lavasoft.test2.bean@ Fe64b9 bean{id= ' 0 ', name= ' none '} Thread-0 com.lavasoft.test2.bean@291aff bean{id= ' 0 ', name= ' none '} Thread-3 com.lavasoft.test2.bean@186db54 bean{id= ' 0 ', name= ' none '} Thread-3 com.lavasoft.test2.bean@186db54 Bean{id= ' 0 ', name = ' None '} Thread-1 com.lavasoft.test2.bean@291aff bean{id= ' 0 ', name= ' none '} Thread-0 Com.lavasoft.test2.bean@291aff Bean{id= ' 0 ', name= ' noNe '} Thread-0 com.lavasoft.test2.bean@291aff bean{id= ' 0 ', name= ' none '} Thread-1 Com.lavasoft.test2.bean@291aff

 Id= ' 0 ', name= ' None '} Process finished with exit code 0


It is clear from the print result that the Tlt object of the mythreadlocal is indeed a, the TL object of the threadlocal in the Tlt object is also one, but when it will be t1t to each thread, The thread will re-create the Bean object and add it to the threadlocal map to use.


Some misunderstandings about threadlocal:
One , threadlocal is an implementation of Java threads

Threadlocal is really about Java threading, but it's not an implementation of Java threads, it's just used to maintain local variables. For each thread, provide its own version of the variant, primarily to avoid threading conflicts, and each thread maintains its own version. Independent of each other, the modification will not affect the other.

Second, threadlocal is relative to each session of

Threadlocal, as the name suggests, is for threads. On Java Web Programming, each user has its own session identifier from the beginning to the session. But threadlocal is not on the conversation floor. In fact, Threadlocal is independent of the user session. It is a server-side behavior that, when the server generates a new thread, maintains its own threadlocal.

For this misunderstanding, the individual believes that the developer should be locally based on the results of some application server tests. As we all know, the general application server maintains a set of thread pools, which means that for each visit, it is not necessarily a new thread. Instead, you have a thread caching pool. For access, first find the existing thread from the cache pool, and if it is used up, it will be reborn into a new thread.

So, because the developers themselves in the test, usually only his own testing, so that the server's burden is very small, so that each visit may be shared with the same thread, resulting in the misunderstanding: each session has a threadlocal

Third, threadlocal is relative to each thread, the user each visit will have a new threadlocal

Theoretically speaking, threadlocal is indeed relative to each thread, each thread will have its own threadlocal. But as mentioned above, a common application server maintains a set of thread pools. Therefore, access by different users may receive the same thread. Therefore, when doing based on theadlocal, care should be taken to avoid the caching of threadlocal variables, causing other threads to access this thread variable

Four, for each user access, threadlocal can be used more

It can be said that threadlocal is a double-edged sword, with the words can play a very good effect. However, if the threadlocal is not well used, it will be the same as the global variable. Code cannot be reused and cannot be tested independently. Because, some classes that could have been reused are now dependent on the threadlocal variable. These classes become unusable if they are not threadlocal on other occasions. Personally feel that Threadlocal used very well in several application occasions, it is worth reference

1, store the current session User: Quake want Jert

2, store Some context variables, such as WebWork's Actioncontext

3, storage session, such as spring Hibernate ORM Session

Related Article

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.