Wechat search [Wugi chat programming], follow me, progress a little bit every day this article has been accepted to Java development treasure book Github, welcome everyone star: github.com/eson15/java…

In the previous section, we summarized the problem of thread-wide data sharing. That is, define a Map, store the name of the current thread and data in the form of key-value pairs in the Map, and then use the data in the current thread according to the name of the current thread from the Map. In this way, data from different threads will not interfere with each other. The ThreadLocal class provides this solution, so we can use ThreadLocal to share thread-wide data.

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(a) {
					int data = new Random().nextInt();
					System.out.println(Thread.currentThread().getName() + " has put a data: " + data);
					threadLocal.set(data);// Throw data directly into threadLocal
					new TestA().getData();
					newTestB().getData(); } }).start(); }}static class TestA {
		public void getData(a) {
			System.out.println("A get data from " + Thread.currentThread().getName() + ":" + threadLocal.get());// Fetch directly from the current thread without any keywords}}static class TestB {
		public void getData(a) {
			System.out.println("B get data from " + Thread.currentThread().getName() + ":" + threadLocal.get());// Fetch directly from the current thread without any keywords}}}Copy the code

ThreadLocal is a Map, but we do not need to set the key. ThreadLocal is a Map, but we do not need to set the key. ThreadLocal is a Map, but we need to set the key. Instead of saving maps one by one,

A ThreadLocal can be accessed easily, but the get() method has no parameters at all. This means that we can only put one data into a ThreadLocal.

ThreadLocal is obviously a container and can only be stored once, so if we have more than one piece of data, we can define a class, encapsulate the data in that class, and then throw it into a ThreadLocal. When we use that class, we can fetch the data from that class.

Ok, so now you have two threads, and each thread has to manipulate its own data, and the data has two: name and age. 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 ++) {// Start two threads
			new Thread(new Runnable() {
				
				@Override
				public void run(a) {
					int data = new Random().nextInt();
					System.out.println(Thread.currentThread().getName() + " has put a data: " + data);

					// Maintain a User for each thread, which holds name and age
					User user = new User();
					user.setName("name" + data);
					user.setAge(data);
					threadLocal.set(user); // Store the user object to the current thread
					
					new TestA().getData();
					newTestB().getData(); } }).start(); }}static class TestA {
		public void getData(a) {
			
			User user = threadLocal.get();// Fetch the user object from the current thread
			System.out.println("A get data from " + Thread.currentThread().getName() + ":" 
					+ user.getName() + ","+ user.getAge()); }}static class TestB {
		public void getData(a) {

			User user = threadLocal.get();// Fetch the user object from the current thread
			System.out.println("B get data from " + Thread.currentThread().getName() + ":" 
					+ user.getName() + ","+ user.getAge()); }}}// Define a User class to store the name and age
class User {
	
	private String name;
	private int age;
	public String getName(a) {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge(a) {
		return age;
	}
	public void setAge(int age) {
		this.age = age; }}Copy the code

This encapsulates multiple data stores, but the above program is not very good, for obvious reasons, in the thread, I have to new an object, then manipulate it, and finally have to throw the object into the current thread. If you have a method like getThreadInstance(), If only the user could call the getThreadInstance() method with any object they want from ThreadLocal, they would always get the object in their own thread scope.

This reminds me of what I did when I was learning JDBC and I took a connection from a ThreadLocal. If there is one in the current ThreadLocal, I take one out. This is the same requirement as here. I should call getThreadLInstance() with User to get a User object from this thread, if it has one, if it doesn’t have one. Exactly the same idea. This design is a little bit like the pattern of the singleton, and I say a little bit like not in essence, but in the structure of the code. Let’s start with a simple singleton code structure:

public class Singleton {
	private static Singleton instance = null;
	private Singleton(a) {// The private constructor blocks the external new
	}
	public static synchronized Singleton getInstance(a) {  // Provide a public method to return an instance of a singleton
        if (instance == null) {  // If there is no instance
            instance = new Singleton();  // A new one
        }  
        return instance;  // Return the instance}}Copy the code

This is the lazy singleton code structure, we can follow this idea to design a way to get the User from the current thread, so modify the program as follows:

public class ThreadScopeShareData {
// There is no need to define threadLocal outside of 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(a) {
					int data = new Random().nextInt();
					System.out.println(Thread.currentThread().getName() + " has put a data: " + data);

					// The static method getThreadLocal is called directly with User to obtain a User object in the scope of this thread
					I don't care how to get objects from the thread. How do I put objects into a threadLocal
					// All I have to do is grab the object from the current thread, because of the User design below
					User.getThreadInstance().setName("name" + data);
					User.getThreadInstance().setAge(data);
					
					new TestA().getData();
					newTestB().getData(); } }).start(); }}static class TestA {
		public void getData(a) {
			// Call this static method, because threadLocal already has it
			User user = User.getThreadInstance();
			System.out.println("A get data from " + Thread.currentThread().getName() + ":" 
					+ user.getName() + ","+ user.getAge()); }}static class TestB {
		public void getData(a) {
			
			User user = User.getThreadInstance();
			System.out.println("A get data from " + Thread.currentThread().getName() + ":" 
					+ user.getName() + ","+ user.getAge()); }}}class User {
	
	private User(a) {}

	private static ThreadLocal<User> threadLocal = new ThreadLocal<User>();
	
	// Synchronized is not a singleton. Each thread can be new, so synchronized is not used.
	// But each threadLocal is a singleton, because it will never be new
	public static /*synchronized*/ User getThreadInstance(a) {
		User instance = threadLocal.get(); // Take the current threadLocal first
		if(instance == null) {
			instance = new User();
			threadLocal.set(instance);// If not, add a new one to threadLocal
		}
		return instance; // Return the User outward
	}
	
	private String name;
	private int age;
	public String getName(a) {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge(a) {
		return age;
	}
	public void setAge(int age) {
		this.age = age; }}Copy the code

After the transformation, the code is much more elegant, the outside world never consider how to take the data in the current thread, you can just take, take out the affirmation is what you want in the current thread object, because inside the object is already written this static method, take out and finished after the operation, also do not need to put them in a threadLocal, Because it’s already in threadLocal, this encapsulates fairly well.

If you have any questions, please feel free to contact us and let us make progress together.

Welcome to pay attention to my original public account: [Wu Ge chat programming], your support is the continuous power of my creation!

The attached:

< 1 > 2020 latest full Java foundation to the project actual combat video: link: pan.baidu.com/s/16IeNr2Z7… Extraction code: YHF7

< 2 > 100000 words Springboot classic learning notes hd belt catalogue PDF: link: pan.baidu.com/s/16AtvPrYp… Extraction code: 13Z9

< 3 > Java the latest comprehensive test (with directory and answers) hd PDF: link: pan.baidu.com/s/1C9u9hJLq… Extraction code: JHMK