Brief introduction:
ThreadLocal is used to provide thread-level variables that are visible only to the current thread. Compare that with the “use locks to control the order of access to shared variables” solution. ThreadLocal avoids the race problem by using a space-for-time scheme, where each thread has its own variable.
This leads to the first question: how do threads maintain their own copies of variables
How do threads maintain their own copies of variables?
1. Take a look at the Thread class first
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
Copy the code
Thread has a threadLocals property that represents the Thread’s local variable. This property is of type ThreadLocal. ThreadLocalMap
2. What’s ThreadLocalMap:
ThreadLocalMap is an internal class of ThreadLocal. It is a map-like structure that stores k-V structure data and encapsulates K-V with Entry. The difference is that the Entry K of a ThreadLocalMap can only be an object of type ThreadLocal and is a weak reference.
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
Thread that is by a kind of Map data structure ThreadLocal. ThreadLocalMap variables to store your own thread.
ThreadLocal. ThreadLocalMap when initialization? ThreadLocal. ThreadLocalMap how to save the values?Copy the code
3. The ThreadLocal in this respect
ThreadLocalMap assigns values, and the entry to the value operation is in its external class ThreadLocal.
Sett (v) calls ThreadLocalMap’s set(this,v) method to store values. (Similar to Map’s put(k,v) method)
public void set(T value) {
//1. Get the current thread instance
Thread t = Thread.currentThread();
//2. Obtain the ThreadLocalMap object from the current thread instance
ThreadLocalMap map = getMap(t);
if(map ! =null)
//3. If Map is not null, the current threadLocl instance is stored as key and value is value
map.set(this, value);
else
//4. If map is null, create a new ThreadLocalMap and store value
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
Copy the code
ThreadLocalMap getEntry(this) = getEntry(this) = getEntry(this)
public T get(a) {
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;
returnresult; }}return setInitialValue();
}
private T setInitialValue(a) {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map ! =null)
map.set(this, value);
else
createMap(t, value);
return value;
}
protected T initialValue(a) {
return null;
}
Copy the code
As can be seen from the code:
- Operation thread ThreadLocalMap attribute for the first time, will initialize a ThreadLocal. ThreadLocalMap,
set(v)
The KV data with parameter Value will be stored,get()
Will be deposited tonull
Is value’s KV data. - ThreadLocal. ThreadLocalMap deposit value operator is ThreadLocal set (v) method, and is the key with the ThreadLocal variable, parameter value.
- ThreadLocal. ThreadLocalMap operator is ThreadLocal values. The get method (v), the key to the current ThreadLocal variable
We can see this visually at the code level:
ThreadLocal threadLocal1 = new ThreadLocal();
// If the thread is assigned a value for the first time, this is similar
// Map map = new HashMap(); Map. put(threadLocal1," first assignment ")
threadLocal1.set("First assignment of a variable");// similar to map.put(threadLocal1," first assignment ")
threadLocal1.set("Variable second assignment");// similar to map.put(threadLocal1," first assignment ")
System.out.println(threadLocal1.get());/ / similar to the map. The get (threadLocal1)Output: Variable second assignmentCopy the code
The nature of the thread’s local variables is now clear. Is the Thread with a similar Map of ThreadLocal. ThreadLocalMap data structure to store the ThreadLocal variable types as Key value, using ThreadLocal to access to delete, ThreadLocalMap operation.
- When we define a ThreadLocal variable, we are defining a Key.
- When we call set (v) method, is to the current ThreadLocal variables as the key, incoming parameters for the value, to the ThreadLocal. ThreadLocalMap save data.
- When we call the get () method, which is at the current ThreadLocal variables as the key, from ThreadLocal. ThreadLocalMap take corresponding data
conclusion
Thread with a similar Map of ThreadLocal. ThreadLocalMap data structure to store the ThreadLocal variables of type as the Key values, using ThreadLocal to access delete, ThreadLocalMap operation
TreadLocal is a thread-local variable. It is helpful to understand TreadLocal from a thread’s perspective
extension
1. Hash conflict resolution of ThreadLocalMap
Linear detection is used to calculate the hash value according to the key. If there is a conflict, the detection is backward, starting from 0 at the end of the hash table until a suitable position is found.
This algorithm also determines that ThreadLocalMap is not suitable for storing large amounts of data.
2. Capacity expansion of ThreadLocalMap is abnormal
The initial size of threadLocalMap is 16 and the loading factor is 2/3. When the size is greater than threshold, the threadLocalMap will be expanded.
During capacity expansion, create an array twice the length of the original array, iterate over the entries in the old array and insert them into the new hash array. During capacity expansion, the value of the entry with the null key is set to NULL. In order to recycle memory, reduce the memory leak problem.