Java Concurrent---threadlocal class and application techniques
The previous section summarizes the thread-wide data-sharing problem, which defines a map, saves the current thread name and data in the thread to the map in the form of a key-value pair, and then gets the data from the current thread from the map based on the current thread name when using the data in the current thread. This allows the data to be different between threads. In fact, the Threadlocal class is to provide us with this workaround, so we can use threadlocal to complete the thread-wide data sharing.
public class Threadscopesharedata {//define a ThreadLocal private static threadlocal<integer> ThreadLocal = new
Threadlocal<integer> ();
public static void Main (string[] args) {for (int i = 0; i < 2; i + +) {new Thread (new Runnable () {
@Override public void Run () {int data = new Random (). Nextint ();
System.out.println (Thread.CurrentThread (). GetName () + "has put a data:" + data);
Threadlocal.set (data), directly to the inside of the threadLocal to throw the information can be new Testa (). GetData ();
New Testb (). GetData ();
}). Start (); } static class Testa {public void GetData () {System.out.println ("A get data from" + thre Ad.currentthread (). GetName () + ":" + threadlocal.get ());/direct fetch, without keyword, it is directly from the current thread to the} static class Testb {public void GetData () {System. OUT.PRINTLN ("B get data from" + Thread.CurrentThread (). GetName () + ":" + threadlocal.get ());/direct fetch, without keyword, it is taken directly from the current thread }
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
Combined with the previous section of the code, you can see, in fact, threadlocal is equivalent to a map, but we do not need to set key, it is the default is the current thread, to put data, direct set can, take the data, direct get can, very convenient, no map saved, But the problem is, threadlocal, although easy access, but get () method has no parameters, that is, we can only put a data into the threadlocal, more than, then how to solve this problem.
Obviously, threadlocal is a container and can only be saved, so if there is more than one data, we can define a class, encapsulate the data into this class, throw it into the threadlocal, take the class, and then go from the class to the data we want.
OK, now there are two threads, each of which operates on its own data and has two data: name and age. According to the above ideas, write a demo, as follows:
public class Threadscopesharedata {private static threadlocal<user> ThreadLocal = new Threadlocal<user> (
); public static void Main (string[] args) {for (int i = 0; I < 2 i + +) {//Open two threads new thread (new Runna ble () {@Override public void run () {int data = new Random (). Nextint
();
System.out.println (Thread.CurrentThread (). GetName () + "has put a data:" + data);
The name and age user user = new user () is maintained in one user,user per thread;
User.setname ("name" + data);
User.setage (data); Threadlocal.set (user);
Save the user Object New Testa () to the current thread (). GetData ();
New Testb (). GetData ();
}). Start (); } static class Testa {public void GetData () {User user = Threadlocal.get ();//remove use from current thread
R Object System.out.println ("A get data from" + Thread.CurrentThread (). GetName () + ":" + user.getname () +
"," + user.getage ()); } static class Testb {public void GetData () {User user = Threadlocal.get ();//remove use from current thread R Object System.out.println ("B get data from" + Thread.CurrentThread (). GetName () + ":" + Use
R.getname () + "," + user.getage ());
}}//define a user class to store the name and age class User {private String name;
private int age;
Public String GetName () {return name;
public void SetName (String name) {this.name = name;
public int getage () {return age;
public void Setage (int age) {this.age = age; }
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26-27--28 29---30 31--32 33 34 35 36 37 38-39 40 41 42 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63-64
This can be a package to achieve the storage of multiple data, but this program is not very good, the reason is obvious, in the thread, I want to new an object, and then operate it, and finally have to throw this object into the current thread. This is not very consistent with the design of ideas, design ideas should be so, can not let users go to new Ah, if there is a similar to the Getthreadinstance () method, How nice it is to use this object to invoke the Getthreadinstance () method for the object that the user wants to take from the threadlocal is always the object within the thread scope.
This reminds me of the time to learn JDBC, from the threadlocal to take connection when the practice, if the current threadlocal have to take out, did not produce a, this is the same as the demand here, I want a user, Then I should use user to invoke the Getthreadlinstance () method to get a user object in this thread, if there is one, if there is no. Exactly the same way of thinking. The design is a bit like a single example, and it's a bit like it's not essentially like, it's a code structure that looks like it. Let's take a look at a simple example pattern code structure:
public class Singleton {
private static Singleton instance = null;
Private Singleton () {//proprietary constructs prevent external new
} public
static synchronized Singleton getinstance () {/ / Provides a public method to return an instance of the external example if
(instance = = null) { //If no instance
instance = new Singleton (); On the new one
} return
instance; Return this instance
}
}
1 2 3 4 5 6 7 8 9 10 11
This is the lazy single example of the code structure, we can follow the idea to design a way to take the user from the current thread, so the program is modified as follows:
public class Threadscopesharedata {//No need to define ThreadLocal outside, put it in the User class/private static threadlocal<user>
threadLocal = new threadlocal<user> ();
public static void Main (string[] args) {for (int i = 0; i < 2; i + +) {new Thread (new Runnable () {
@Override public void Run () {int data = new Random (). Nextint ();
System.out.println (Thread.CurrentThread (). GetName () + "has put a data:" + data);
This is the direct use of user to call Getthreadlocal this static method to obtain a user object within the scope of this thread//This is much more elegant, I don't care how to get the object in the thread, how to put the object in the Threadlocal I just take it, and it's definitely the object in the current thread, because the design user.getthreadinstance () in the User class below. SetName ("name"
+ data);
User.getthreadinstance (). setage (data);
New Testa (). GetData ();
New Testb (). GetData ();
}). Start (); }} Static Class Testa {public void GetData () {//or call this static method to take, because it has just been taken once, the threadlocal already has the user user = Us
Er.getthreadinstance (); System.out.println ("A get data from" + Thread.CurrentThread (). GetName () + ":" + user.getname () + ",
"+ user.getage ());
} static class Testb {public void GetData () {User user = User.getthreadinstance (); System.out.println ("A get data from" + Thread.CurrentThread (). GetName () + ":" + User.getnam
E () + "," + user.getage ()); Class User {Private User () {} private static threadlocal<user> ThreadLocal = new threadlocal& Lt
User> (); Note that this is not a single example, each thread can be new, so there is no synchronized,//But each threadlocal is a single case, because there will be no new public static/*synchronized*/User Instance = new User (); Threadlocal.set (instance)//if not on the new one put in threadLocal} return instance;
Returns the user} private String name outward;
private int age;
Public String GetName () {return name;
public void SetName (String name) {this.name = name;
public int getage () {return age;
public void Setage (int age) {