🏅 author Xiao SAN is just graduated from the full stack engineer, wrote the technical article is basically in the process of learning notes sorted out, you can give little brother a little praise if you like after reading. 🏅 exception little brother still has a programmer exchange group, welcome everybody big guy to touch fish ha. Click add group

What is a ThreadLocal

ThreadLocal, also known as thread local variable, is used to solve the problem of data inconsistency caused by concurrent data in multiple threads. ThreadLocal for each thread is to provide the copy of the variable, making each thread at a time to access is not the same object, thus isolating the multiple threads for data sharing, the result is nothing but take the memory, also greatly reduced the thread synchronization performance brought by the consumption, and reduced the complexity of the thread concurrency control.

In summary: ThreadLocal is suitable for situations where each thread needs its own instance and the instance needs to be used in multiple methods, i.e. variables are isolated between threads but shared between methods or classes

What’s the difference between ThreadLocal and Synchronized?

Both ThreadLocal and Synchonized are used to deal with multi-threaded concurrent access, but there are some essential differences between them:

Synchronized is a mechanism that uses locks to make variables or code blocks accessible to only one thread at a time. ThreadLocal provides each thread with a copy of a variable, so that each thread has access to a different object at a certain time. This isolates data sharing between multiple threads.

Note: ThreadLocal cannot use atomic types, only Object types

Simple use of ThreadLocal

public class ThreadLocaTest { private static ThreadLocal<String> local = new ThreadLocal<String>(); Println (STR + ":" + local.get()); static void print(String STR) {system.out.println (STR +" :" + local.get()); // Remove the local variable localvar.remove (); } public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() { public void run() { ThreadLocaTest.local.set("xdclass_A"); print("A"); // Print the local variable system.out.println (" after clearing: "+ local.get()); } },"A").start(); Thread.sleep(1000); new Thread(new Runnable() { public void run() { ThreadLocaDemo.localVar.set("xdclass_B"); print("B"); System.out.println(" after clearing "+ localvar.get ()); } },"B").start(); }}Copy the code

Xdclass_A is null, and xdclass_B is null, indicating that the two threads have obtained their own variables, and the variables obtained between them are not corrupted.

This section describes the scenarios of ThreadLocal core applications

ThreaLocal allows each thread to store information independently, which makes it easier for other methods on the same thread to get the information. Since each thread may obtain information differently, after the previous method stores information, subsequent methods can directly obtain the information through ThreadLocal. Avoids passing parameters, which is similar to the concept of global variables. For example, information transfer after user login token decryption, user permission information, user name obtained from user system

If method 1 of thread A creates variable A and method 2 is on the same thread as method 1, then variable A is created and shared.

Public static ThreadLocal<LoginUser> ThreadLocal = new ThreadLocal<>(); LoginUser loginUser = new LoginUser(); loginUser.setId(id); loginUser.setName(name); loginUser.setMail(mail); loginUser.setHeadImg(headImg); threadLocal.set(loginUser); Threadlocal.getxxx = threadLocal.getxxxCopy the code

How can ThreadLocal be used to solve thread-safety problems

In our normal SpringWeb project, we would normally split the business into controllers, services, daos, and so on, and know that the annotation @autowired uses singleton patterns by default. When the Dao layer uses a singleton, there is only one Connection that is responsible for connecting to the database. In this case, if all threads are connected to the database, the thread will be unsafe. How to solve this problem?

Connection threads assembled in the Dao layer are definitely safe, and the solution is to use ThreadLocal methods. Each time a thread requests a Connection, it will fetch the Connection from ThreadLocal. If the value is null, the Connection will be stored in ThreadLocal. Each thread holds its own Connection. Each thread maintains its own data to achieve thread isolation.

A cautious scenario for ThreadLocal

First point (thread pool calls ThreadLocal) : Because thread pool management is thread reuse, threads in a thread pool are very difficult to terminate, and most likely never terminate. This means that the duration of a thread is inestimable, even consistent with the lifetime of the JVM.

Second (in asynchronous applications) : The passing of parameters to ThreadLocal is unreliable, because the thread that sends the request does not wait for the remote to return the result. After the actual result is returned, another thread may be processing it.

Third, it is recommended to call the remove () method after using ThreadLocal. This will prevent memory overruns because ThreadLocal is a weak reference. ThreadLocal will be cleaned up in garbage collection if it is not strongly referenced, but not if it is strongly referenced.

Easy to understand the basic source code of ThreadLocal + principle

Thread t = thread. currentThread = ThreadLocalMap (); If it is not empty, the variable value to be saved is updated directly, otherwise a threadLocalMap is created and assigned.

So what does ThreadLocalMap do? Let’s take a look and see that ThreadLocalMap is an internal static class of ThreadLocal. This class consists mainly of entries to hold data and is a weak reference to inheritance. We use ThreadLocal as the key inside the Entry, and we use our own value as the value

Now that the set and ThreadLocalMap methods are out of the way, let’s look at the get methods. The ThreadLocalMap of the current thread is obtained, and then the map is judged. If the map data is empty, then the stored value is retrieved. If the data is null, initialization begins, and the result of initialization is that Theradlocalmap stores null values.

It can be seen that basically all operations have this ThreadLocalMap. This class does not realize the interface of Map, so it is just a common Java class, but the class implemented is similar to the function of Map. Data is stored with Entry, which is inherited from WeakReference and stored with a key-value pair. The key is a reference to ThreadLocal. Each Thread has a ThreadLocalMap object, and each new Thread instantiates a ThreadLocalMap and assigns values to the member variable threadLocals.

What is the problem with a ThreadLocal key if it is a strong reference?

What is a weak reference? (Little white please see, big guy please skip ~)

In Java, all but the basic data types are reference types, and Java divides reference types into strong reference, soft reference, weak reference and virtual reference according to the length of their life cycle. Normally we only apply strong reference types, and other reference types can be seen in interviews or when reading the source code.

Object obj = new Object ()

A SoftReference, which has a shorter lifetime than a strong reference, is delivered via the SoftReference class. If there is enough memory, the garbage collector does not reclaim it. This is because the JVM attempts to reclaim the object specified by the soft reference when it believes that memory space is insufficient, meaning that the JVM will clean up the soft reference object before throwing an OutOfMemoryError.

The use scenario of soft reference: it is suitable for cache. When the memory space is sufficient, the cache is stored in the memory. If the memory space is insufficient, the cache can be reclaimed

WeakReference: WeakReference is realized through WeakReference class, and its life cycle is shorter than soft reference (each one is shorter than the other). When garbage collection is carried out, the object will be reclaimed no matter whether the memory space is enough

Use scenario: If an object is used only occasionally and you want to be able to retrieve it whenever you use it, but you don’t want to affect the object’s garbage collection, you can consider using weak references to point to the object.

Having said so much, I still haven’t covered the interview question. Now let’s talk about how to answer the interview question

Why is ThreadLocal a WeakReference?

If the value of a ThreadLocalMap is null, the reference state of a ThreadLocalMap will still be null. If the value of a ThreadLocalMap is not deleted manually, the reference state of a ThreadLocalMap will not be reclaimed. This will result in a leak of Entry memory

If a weak reference to a ThreadLocal is discarded, the weak reference to a ThreadLocal will be discarded even if it is not removed manually. The value is cleared the next time ThreadLocalMap calls the set/get/remove methods.