preface
To get through ThreadLocal diagrammatically, and hopefully you have some JVM foundation, so it tastes better.
I believe that everyone is not unfamiliar with ThreadLocal, commonly used in work, but also a high-frequency interview questions, but most people on the understanding of ThreadLocal may only be “ThreadLocal variables, Map structure”, read this article to let everyone really understand ThreadLocal, to everyone work to bring help, It also gives the interview something to talk about.
Outline of the content
Java object reference level
Before we talk about ThreadLocal, let’s start with a little preknowledge about Java object reference levels.
In order to enable programs to control the life cycle of an object more flexibly, the JDK has divided the reference level of an object into four levels: strong reference, soft reference, weak reference, and virtual reference.
Strong reference StrongReference
A strong reference is one of the most common objects. It is a non-recyclable resource, and the garbage collector (G C) will never reclaim it. J V M would rather throw an OutOfMemoryErrorM exception and terminate the program than reclaim a strong reference object, even if the program runs out of memory.
Soft reference SoftReference
If the object is a soft reference, then its nature is optional, because when memory space is sufficient, G C will not reclaim it, but when memory space is tight, G C finds that it only has soft references, it will reclaim the object, so soft reference object is suitable for memory sensitive cache object.
If an object is referenced only by a SoftReference, it is a SoftReference level object. Because an object can be referenced in multiple places, it may be strongly referenced elsewhere.
A weak reference WeakReference
Weak reference objects have a shorter life cycle than soft reference objects. Whenever G C finds that it has only weak references, it will reclaim it regardless of whether there is enough memory, but G C is a low priority thread, so it does not necessarily find objects with only weak references very quickly.
An object is a WeakReference level object only when it is referenced by WeakReference. Because an object can be referenced in multiple places, an object referenced by WeakReference may be strongly referenced in other places.
Phantom reference PhantomReference
As the name suggests, a virtual reference is a virtual reference, and unlike several other references, it does not determine the life cycle of the object.
If an object has only virtual references, it is just as likely to be reclaimed by G at any time as if it had no references at all.
Is there any difference between a virtual reference and a weak reference? The differences are as follows
- If the object referenced by SoftReference or WeakReference is not reclaimed, you can use the GET method to obtain the real object address
- PhantomReference always returns null using the get method
There is no way to get the real address of an object through a virtual reference.
summary
SoftReference, WeakReference, and PhantomReference in Java can be understood as object reference level wrapping classes. The corresponding wrapping classes are used in the project to assign object reference levels.
In the virtual reference graph, ReferenceQueue (ReferenceQueue) appears. The ReferenceQueue is used in cooperation with object reference level wrapping classes (SoftReference, WeakReference, PhantomReference). When the object pointed to by the object reference level wrapping class is garbage collected, The object reference level wrapper class is appended to the reference queue so that operations such as G C related statistics or additional data cleaning can be performed from the reference queue.
ThreadLocal
Many places of ThreadLocal are called thread-local variables, and some places are called thread-local storage, which means much the same thing. ThreadLocal creates a copy of a variable in each thread, and each thread can access its own internal copy variable.
What is a ThreadLocal
The Thread class declares the member variables threadLocals, which are true thread-local variables, so each Thread has its own thread-local variables, so thread-local variables have Thread isolation, which is inherently thread-safe.
From the picture above you can see threadLocals member variable class is ThreadLocal ThreadLocalMap, namely is to provide the inner class ThreadLocal, therefore the Thread Thread local variable to create, add, obtain, delete, to realize the core, It must be around threadLocals, so developers implement functionality around threadLocals, encapsulating and reusing code implementations for subsequent reuse. ThreadLocal is a thread-local variable utility class provided by J D K. Thread-local variables are already implemented, out of the box, for the benefit of developers.
ThreadLocal is a common method
- Set: Sets a variable for the current thread, with the current ThreadLocal as the index
- Get: Gets the current thread variable, with the current ThreadLocal as the index
- InitialValue (hook method needs subclass implementation) : the thread local variable is initialized by dependency. When the thread local variable is null during get, the contents of the initialValue are executed
- Remove: Clears the current thread’s ThreadLocal index and mapped elements
A Threa can have multiple ThreadLocal key-value pairs (stored in the ThreadLocalMap structure), and because the ThreadLocalMap depends on the current Thread, the ThreadLocalMap will be destroyed when the Thread is destroyed. So the life cycle of ThreadLocalMap is bound to Thread.
A Thread can use a local Thread variable across multiple methods. If you want a variable to be shared between multiple methods of a Thread and be Thread safe, use a ThreadLocal (ps: Consider whether a variable is shared by multiple methods in the Thread’s lifetime or by multiple Threads!) .
ThreadLocal source
Let’s first look at the thread local variable code implemented by the User class
The methods are initialValue, GET, set, and remove, and the source code of these methods is then parsed.
ThreadLocalMap structure
For the rest of the source code parsing experience, it’s worth covering ThreadLocalMap, which, as the name suggests, is a Map structure, but this article is not about maps, so let’s go through that quickly in the previous figure.
The ThreadLocalMap structure is very clear from the figure above. If you have noticed that ThreadLocal is held by a weak reference, you may have noticed that ThreadLocal is held by a weak reference.
Why is ThreadLocal weakly referenced? This question will be clarified later, and finally the source map of ThreadLocalMap.
Get gets variables
Complete the following steps
- Get current thread
- Gets the local variable for the current thread
- The thread local variable was not created. The setInitialValue method is used to initialize the variable and return the value
- If the Entry is null, we initialize it with the setInitialValue method and return the value. Otherwise, we return the value from the Entry
The initialValue method
Complete the following steps
- Triggered by the GET method
- Perform initialization and get value
- Get current thread
- Gets the current thread-local variable
- If the current thread-local variable exists, ThreadLocal evaluates to the value of the index setting mapping, otherwise create the thread-local variable and do the subsequent setting
- Returns the value value
Set variable
Complete the following steps
- Get current thread
- Gets a thread-local variable
- If the local variable is not empty, the current ThreadLocal sets the value of the mapping to the index. Otherwise, create the ThreadLocal variable and do the subsequent setting
Remove Remove variable
Complete the following steps
- Get an Entry array
- The current ThreadLocal calculates the index
- Retrieve the Entry element based on the index (if the first miss, loop until NULL)
- Clear the Entry element
summary
Source code is very simple, the core of the three ThreadLocal ThreadLocal variable utility class (as an index), Entry basic elements (consisting of weak reference wrapping class ThreadLocal and value), Entry array container, here the process is very clear, ThreadLocal calculates the array index, Use ThreadLocal and value to build Entry elements, and eventually put them into the Entry container. I believe everyone can write them out.
Why weak references
Why use weak references to ThreadLocal in an Entry? By the way, what happens if you use strong references?
The code above is only for people to understand why weak references are used, and it is not normally used in development (if it does, the programmer will have to kill it).
Back to the topic, let’s quickly parse the code. First, ThreadContextTest holds a private static variable ThreadLocal, and ThreadContextTest is forbidden to instantiate. The execution of the static method run then triggers the static block to set the User variable for the ThreadLocal and eliminate the strong ThreadLocal reference, at which point the local variable of the current thread has the Entry element.
In the normal process, ThreadLocal executes the get method. Get will use the current ThreadLocal to calculate the index and finally obtain the Entry element. However, the problem is as follows.
We don’t know what is the key, how to obtain the value of mapping, by the same token, no entrance to get to ThreadContextTest. ThreadLoca, nature can’t get Entry element mapping.
In the design, Map structure is used to store data, but the value cannot be obtained through key. This design is obviously unreasonable, and because key and value values are strong references, G C cannot be reclaimed, resulting in memory overflow.
Therefore, J D K optimizes this unreasonable design scenario by using weak references for ThreadLocal in the Entry. When G C finds that it has only weak references, it will recycle.
The meaning behind remove
That’s not all. It leaves a little tail. Everyone knows that Entry uses a weak reference to ThreadLocal, but value is a strong reference.
If you use a soft or weak reference, you will have a big problem. If you use a soft or weak reference, you will have a big problem. If you use a soft or weak reference, you will have a big problem. Prevent memory overflow.
Remember that before? The life cycle of the thread local variable is bound to the thread. Generally, the life cycle of the thread is relatively short. When the thread ends, the thread local variable will be destroyed naturally.
Business rapidly changing, the most part the life cycle of a thread is shorter, but also business scenarios can lead to a longer life cycle threads, thread may even be an infinite loop, this is you can’t anticipate, quantity once it is easy to memory, so personal advice after use clean ThreadLocal in time, for the following reasons
- Long life thread scenarios
- Infinite loop thread scenario
- Thread pool scenarios (because thread pools can reuse threads, and the framework used by the company may customize the thread pool, you can’t guarantee that it will remove the thread pool for you)
chatter
I wish everyone a happy New Year and all the best!! Blogger two weeks a liver, although the cycle is a little long, but the quality is guaranteed, code text is not easy, if you think this article is helpful to you, welcome to share with your friends, but also to a Xing point “like + collection”, this is very important to a Xing, thank you, to you little sisters little brothers, we see next time!
About me
Public number: “program ape a star” focus on technical principles, source code, through graphical output technology, here will share operating system, computer network, Java, distributed, database and other original articles, looking forward to your attention.