ThreadLocal ThreadLocal ThreadLocal ThreadLocal ThreadLocal ThreadLocal
ThreadLocal parsing
Basic Understanding
A ThreadLocal creates a copy of a variable in each thread, so that each thread can access its own copy of the variable.
1.1 role
- Thread concurrency: In the case of multi-threaded concurrency
- Passing data: We can use ThreadLocal to pass common variables in different components on the same thread
- Thread isolation: Variables in each thread are independent and do not affect each other
1.2 Basic Methods
- Public void set(T value) Sets the local variable bound by the current thread
- Public T get() gets the local variable of the current thread binding
- Public void Remove () Removes local variables bound by the current thread
- Protected T initialValue() specifies the initialValue
1.3 Getting Started
Requirement: Simulate multiple thread set values and fetch the values set by that thread
The synchronized version
ThreadLocal version
To compare
Both approaches seem to solve the problem, but what about efficiency?
Synchronized: A time-for-space synchronization mechanism provides only one variable, which allows different threads to queue up for access. Synchronized focuses on resource synchronization between multiple threads
ThreadLocal: A ThreadLocal provides a copy of a variable for each thread in a time-for-space manner, allowing simultaneous access without interference. It focuses on isolating data between threads
Of course, each method applies to different scenarios
Two principles of inquiry
2.1 Internal Structure
Before JDK1.8, each ThreadLocal creates a Map, uses the thread as the Map key, and stores local variables as the Map value, thus achieving local variable isolation for each thread.
After JDK1.8: Each Thread maintains a ThreadLocalMap, whose key is the ThreadLocal instance itself and whose value is the actual Object to store.
2.2 Source code analysis of ThreadLocalMap
- The important parameters
Storage structure – Entry
// Specify that dead is WeakReference
static class Entry extends WeakReference<ThreadLocal<? > > {
/** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<? > k, Object v) { super(k); value = v; }Copy the code
}
- Hash conflict resolution
Hash conflict basic knowledge
Hashing is a solution to improve efficiency by recompressing data. However, the hash value generated by the hash function is limited, and the data may be more, resulting in different data corresponding to the same value after the hash function processing. That’s where the hash conflict comes in.
- Open address method
(1) Linear detection
When determining values in order, if the value of a data already exists, add one unit to the previous value until no hash conflicts occur.
(2) Re-square detection
In order to determine the value, if the value of the data already exists, add 1 square units to the original value. If the value still exists, subtract 1 square units. And then 2 squared, 3 squared and so on. Until no hashing occurs.
(3) Pseudo-random detection
When deciding values in order, if some data already exists, a random number is generated by random function, and a random number is added on the basis of the original value until no hash conflict occurs.
- Chained Address method (Hash conflict resolution for HashMap)
For the same value, join using a linked list. Use arrays to store each list.
Advantages:
(1) The zipper method is simple to deal with conflicts, and there is no stacking phenomenon, that is, non-synonyms will never conflict, so the average search length is short;
(2) Because the node space on each linked list in the zipper method is applied dynamically, it is more suitable for the situation that the table length cannot be determined before table construction;
(3) In order to reduce conflicts, the open addressing method requires a small loading factor α, so a lot of space will be wasted when the node scale is large. In the zipper method, α≥1 is desirable, and when the node is large, the pointer field added in the zipper method can be ignored, so space is saved.
(4) In the hash table constructed by zipper method, the operation of deleting nodes is easy to realize. Simply delete the corresponding nodes on the linked list.
Disadvantages:
When Pointers occupy a large space, space will be wasted. If space is used to increase the size of hash table, then the efficiency of open address method will be improved.
- Establish public overflow areas
Create a public overflow area to store all hashing data.
- Then the hash method
The conflicting hash values are hashed again until there are no hash conflicts.
conclusion
-
The hash algorithm uses hashCode & (size-1), which is a more efficient implementation of hashCode % size. Because of this algorithm, size must be a full power of 2, which also ensures that the number of hash collisions is reduced without the index crossing the boundary.
-
Linear detection method: Assume that the length of the current table is 16, that is, if the hash value of the calculated key is 14, if the table[14] already has a value and its key is inconsistent with the current key, then a hash conflict will occur. In this case, add 14 and 1 to get 15, and judge by taking table[15]. At this time, if the conflict is still returned to 0, take table[0], and so on, until it can be inserted.
2.3 Basic methods
- Public void set(T value) Sets the local variable bound by the current thread
- Public T get() gets the local variable of the current thread binding
- Public void Remove () Removes local variables bound by the current thread
- Protected T initialValue() specifies the initialValue
Set method
The get method
The remove method
/ * *
Public void remove() {// Obtain the ThreadLocalMap object ThreadLocalMap m = getMap(Thread.currentThread()); // If (m! Map. remove // Delete the corresponding entity entry m.remove(this) with the current ThreadLocal key; }Copy the code
The initialValue method
/ * *
-
Returns the initial ThreadLocal of the current thread
-
The first call to this method occurs when a thread accesses the ThreadLocal value of this thread through the GET method
-
InitialValue will not be called by the thread unless the set method is called first.
-
Normally, this method is called at most once per thread.
-
This method simply returns null {@code null};
-
If a programmer wants a ThreadLocal thread-local variable to have an initial value other than null,
-
This method must be overridden by subclass {@code ThreadLocal}
-
Typically, this can be done through anonymous inner classes
-
@return The initial value of the current ThreadLocal
* /
protected T initialValue() {
return null;
Copy the code
}
Three interviews
3.1 Why are ThreadLocalMap keys designed to be weak references?
- Concepts related to memory leaks
Memory overflow: Indicates that there is not enough Memory for applicants to use.
Memory leak: A Memory leak refers to a program that fails to release or release dynamically allocated heap Memory for some reason, resulting in a waste of system Memory, slowing down the program and even crashing the system. The accumulation of memory leaks eventually leads to an overflow of memory.
- Reference related concepts
Strong references As long as the reference exists, the garbage collector will never collect it
Soft references are not mandatory and are reclaimed before memory overflow
Weak references are collected on the second garbage collection
The object value cannot be retrieved by reference
Weak references have one more layer of protection than strong references: The ThreadLocal of a weak reference is reclaimed, and the corresponding value is cleared the next time ThreadLocalMap calls any of the set, GET, or remove methods, thus avoiding memory leaks.
Well, that’s all for today’s article, hoping to help those of you who are confused in front of the screen