Interpretation of ThreadLocal source code

1、 Introduce

public class Thread implements Runnable {
    /* 前面略  */

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
    /* 后面略  */
 }

First of all, we can see that there is an attribute threadlocals in the thread. Its type is threadlocalmap, and its encapsulation type is default (indicating that it can only be seen in the package). JDK introduces it this way: the ThreadLocal value related to this thread, and the mapping is maintained by the ThreadLocal class. What do you mean? Let's see what threadlocalmap is!

public class ThreadLocal<T> {
   /* 前面略  */

    static class ThreadLocalMap {

        /**
         * The entries in this hash map extend WeakReference,using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced,so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k,Object v) {
                super(k);
                value = v;
            }
        }
   /* 后面略  */
   }
}

It can be seen from the class definition that ThreadLocal supports generics, and threadlocalmap is an internal class of ThreadLocal, The encapsulation type is also default (indicating that it can only be seen in the package). This is how JDK introduces it: threadlocalmap is a custom hash map, which is only suitable for maintaining thread local values. In addition, in order to control the storage capacity and avoid memory leakage, the hash table entries use weak references as keys (the life cycle of weakly referenced objects is recycled until the next garbage collection). Threadlocalmap uses the static internal class entry (which can be compared with the entry in the map) to store the actual key and value.

From the above introduction, we can roughly think that ThreadLocal is a thread related class used to store and maintain thread local values.

2、 Interpretation of set (t value) method

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this,value);
        else
            createMap(t,value);
    }
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
    void createMap(Thread t,T firstValue) {
        t.threadLocals = new ThreadLocalMap(this,firstValue);
    }

You can see that the set (t value) method is very simple. It is to maintain the threadlocals attribute of thread. If the attribute does not exist, create one with the current ThreadLocal instance as the key; If this attribute exists, it will be assigned directly.

3、 Interpretation of get() 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);
        return value;
    }
    protected T initialValue() {
        return null;
    }

The method of get () is also very simple. It is to get the value from the threadlocals property of thread. If it cannot be obtained, assign the value of initialvalue () to the threadlocals property of thread and return it. The initialvalue () method is a protected method. It returns null by default. We can override it when creating ThreadLocal to represent the default values of all threads.

    // java8 的方式
    ThreadLocal<Boolean> threadLocal1 = ThreadLocal.withInitial(() -> false);
    // 
    ThreadLocal<Boolean> threadLocal2 = new ThreadLocal<Boolean>() {
        @Override
        protected Boolean initialValue() {
            return false;
        }
    };

4、 Summary

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>