Home >Java >javaTutorial >Detailed introduction to ThreadLocal in Java (code example)
This article brings you a detailed introduction (code example) about ThreadLocal in Java. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
ThreadLocal is basically not used in project development, but interviewers prefer to ask this type of questions; so it is still necessary to understand the functions and principles of this class.
What is ThreadLocal
ThreadLocal is a class that will create a separate copy of variables for each thread in multiple threads; when using ThreadLocal to maintain variables, ThreadLocal will create a separate copy of variables for each thread to avoid Data inconsistency caused by multi-threaded operation of shared variables;
Generally speaking, ThreadLocal
is not used in actual industrial production It is common, but it can solve some framework problems when used in many frameworks; such as transactions in Spring, the scope Scope
in Spring and the Bean of
Request can be solved using ThreadLocal.
1. Use ThreadLocal variables to define attributes that need to be accessed by multiple threads; the following is an example of the DBConnectionFactory class that is most commonly used on the Internet
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBConnectionFactory { private static final ThreadLocal<Connection> dbConnectionLocal = new ThreadLocal<Connection>() { @Override protected Connection initialValue() { try { return DriverManager.getConnection("", "", ""); } catch (SQLException e) { e.printStackTrace(); } return null; } }; public Connection getConnection() { return dbConnectionLocal.get(); } }
In this way, in the Client When obtaining a Connection, the Connection obtained by each thread is unique to that thread, achieving thread isolation of the Connection; so there is no thread safety issue
1. It mainly uses a ThreadLocalMap type variable threadLocals in the Thread object, which is responsible for storing the Connection object of the current thread. The dbConnectionLocal variable is used as the Key, and the newly created Connection object is used as the Value; in this case, the thread first If it does not exist when reading, ThreadLocal's initialValue method will be called to create a Connection object and return;
The specific code for allocating a copy of the variable to the thread is as follows:
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
1. First get the current Thread object t, and then obtain the member attribute threadLocals
# of ThreadLocalMap from thread t. 2. If the threadLocals of the current thread have been initialized (that is, not null) and there is a value with the current ThreadLocal object as the key, then directly Return the object to be obtained by the current thread (Connection in this example);
3. If the threadLocals of the current thread have been initialized (that is, not null) but there is no object with the current ThreadLocal object as the key, then Re-create a Connection object, and add it to the threadLocals Map of the current thread, and return
4. If the threadLocals property of the current thread has not been initialized, re-create a ThreadLocalMap object, and create a Connection object and Added to the ThreadLocalMap object and returned.
If it exists, it will be returned directly. It is easy to understand. So what is the code for how to initialize?
private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }
1. First, call the overloaded initialValue method we wrote above to generate A Connection object
2. Continue to check whether the threadLocals of the current thread are empty. If the ThreadLocalMap has been initialized, then directly add the generated object to the ThreadLocalMap. If it is not initialized, create and add the object to it. ;
At the same time, ThreadLocal also provides a method to directly operate threadLocals in the Thread object
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
In this way, we can also not implement initialValue and put the initialization work in the getConnection method of DBConnectionFactory:
public Connection getConnection() { Connection connection = dbConnectionLocal.get(); if (connection == null) { try { connection = DriverManager.getConnection("", "", ""); dbConnectionLocal.set(connection); } catch (SQLException e) { e.printStackTrace(); } } return connection; }
Then after we read the code, we clearly understand why ThreadLocal can achieve multi-thread isolation of variables; in fact, it uses the Map data structure to cache the current thread, and when it is used, it is cached from this thread. Just get it from the threadLocals object, and the key is the current thread;
Of course, if you get the objects in the Map in the current thread and operate them under the current thread, there will definitely be no thread concurrency problems. Of course, variables can be used Threads are isolated;
Now that we know what ThreadLocal is, and how to use ThreadLocal and its basic implementation principles, can we end it? In fact, there is another question: what is ThreadLocalMap? Object, why use this object?
Essentially speaking, it is a Map, but this ThreadLocalMap is a little different from the Map we usually see
1. It does not implement the Map interface;
2. It has no public methods and at most one default constructor, because this ThreadLocalMap method is only called in the ThreadLocal class and is a static internal class
3. The Entry implementation of ThreadLocalMap inherits WeakReference
4. This method only uses an Entry array to store Key and Value; Entry is not in the form of a linked list. Instead, only one Entry is placed in each bucket;
The above is the detailed content of Detailed introduction to ThreadLocal in Java (code example). For more information, please follow other related articles on the PHP Chinese website!