ThreadLocal novella: unravel the mystery ThreadLocal

Summary:

ThreadLocal to provide thread-level variable, which is visible only to the current thread. Compared with the " use locks to control access to shared variables order solutions". ThreadLocal through space for time program, to avoid competition, each thread has its own variables.

At this time, the first question arises: how to maintain the thread of their own copy of the variable

How to maintain a copy of the variable thread of their own?

1. First look Thread class
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
复制代码

Thread has a threadLocals property indicates the local variable thread. This type of property is ThreadLocal.ThreadLocalMap

2.ThreadLocalMap is valid:

ThreadLocalMap is ThreadLocal inner class, he is the class Map structure, configuration data is also stored KV, and the Entry package KV. The difference is the Entry ThreadLocalMap ThreadLocal K-only type of object, 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;
            }
        }
复制代码

That thread to thread variable is stored by a class of their own Map data structure ThreadLocal.ThreadLocalMap.

ThreadLocal.ThreadLocalMap 何时初始化?
ThreadLocal.ThreadLocalMap 如何存取值?
复制代码
3.ThreadLocal deity

An inlet in its outer ThreadLocalMap ThreadLocal class assignment, the value of the operation.

ThreadLocalMap call within sett (v) Method set (this, v) stored-value method. ( Similar to the Map put (k, v) Method )

public void set(T value) {
    //1. 获取当前线程实例对象
    Thread t = Thread.currentThread();
    //2. 通过当前线程实例获取到ThreadLocalMap对象
    ThreadLocalMap map = getMap(t);
    if (map != null)
        //3. 如果Map不为null,则以当前threadLocl实例为key,值为value进行存入
        map.set(this, value);
    else
        //4.map为null,则新建ThreadLocalMap并存入value
        createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
}
复制代码

get () method call ThreadLocalMap in getEntry (this) method values ( similar to the Map of get (k) method )

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();
    }

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;
}
protected T initialValue() {
        return null;
}
复制代码

It can be seen by the code:

  • The first ThreadLocalMap property when operating the thread, initializes a ThreadLocal.ThreadLocalMap, set(v)will be credited KV data to the Value parameter, get()it will be credited to nullas KV value of the data.
  • Operator ThreadLocal.ThreadLocalMap stored-value is ThreadLocal.set (v) method, and the current ThreadLocal variable key, the parameter to value.
  • Operator ThreadLocal.ThreadLocalMap value is ThreadLocal.get (v) method, key variables for the current ThreadLocal

We understand from the code level, this intuitive operation:

ThreadLocal threadLocal1 = new ThreadLocal();

//如果第一次给线程赋值,此处类似
// Map map = new HashMap(); map.put(threadLocal1,"变量第一次赋值")
threadLocal1.set("变量第一次赋值");//类似map.put(threadLocal1,"变量第一次赋值")

threadLocal1.set("变量第二次赋值");//类似map.put(threadLocal1,"变量第一次赋值")

System.out.println(threadLocal1.get());//类似map.get(threadLocal1)

输出:变量第二次赋值
复制代码

At this point the nature of the thread local variables to clear. It is Thread ThreadLocal.ThreadLocalMap with similar data structure stored in the Map ThreadLocal Key type variable value, and used to access ThreadLocal delete operation ThreadLocalMap .

  • When we define a ThreadLocal variable when, in fact, that is the definition of a Key .
  • When we call to set (v) method, that is, the current ThreadLocal variable key, its argument is value, the data stored in the ThreadLocal.ThreadLocalMap.
  • When we call get () method, that is, the current ThreadLocal variable key, take the corresponding data from ThreadLocal.ThreadLocalMap

to sum up

Thread with a structurally similar ThreadLocal.ThreadLocalMap Map data to be stored as a variable of type ThreadLocal Key value, and with access to ThreadLocal delete operation ThreadLocalMap

TreadLocal is thread-local variables, from the departure angle of the thread , look ThreadLocal, our understanding TreadLocal very helpful

Spread

1.ThreadLocalMap of Hash conflict resolution

Detecting linear manner, according to the calculated hash value key, if a conflict occurs, the backward detection, the time when the end of the hash table starts again from 0, until a suitable location.

This algorithm also determines the ThreadLocalMap not suitable for mass data storage.

2.ThreadLocalMap expansion problem

threadLocalMap initial size of 16, load factor of 2/3, when the size is greater than the threshold, the expansion will be performed.

When the expansion, a new array of size twice the original length of the array, the array then traverse the old entry and inserts it into the new hash array, at the time of expansion, will set to the key value of the null value of Entry It is null. to reclaim memory, reducing memory leaks.

Guess you like

Origin juejin.im/post/5dcb58f2f265da4d3f44c5a1