Detailed InheritableThreadLocal

Detailed https://www.jianshu.com/p/94ba4a918ff5 InheritableThreadLocal

 

InheritableThreadLocal-- parent thread pass local variables to sub-thread of solutions and analysis
https://blog.csdn.net/hewenbo111/article/details/80487252

1 Introduction

In the last  ThreadLocal explain  , we detail the principles and design ThreadLocal, ThreadLocal from the analysis of the source code level. ThreadLocal but the beginning of the design is to bind the current thread, if you want the current thread ThreadLocal can quilt threads, implementation will be difficult (it requires the user to pass in the code). In this context, InheritableThreadLocal came into being.

Inheritable thread-local variables are used in preference to ordinary thread-local variables when the per-thread-attribute being maintained in the variable (e.g., User ID, Transaction ID) must be automatically transmitted to any child threads that are created.

2, application

Call chain track: in the call chain system design in order to optimize the system speed, uses multi-threaded programming, in order to ensure the call chain ID can naturally transfer between multiple threads need to be considered ThreadLocal delivery problems (most systems will use the thread pool technology, which has just InheritableThreadLocal can be resolved, I will introduce the relevant technology in another article).

3、InheritableThreadLocal类

InheritableThreadLocal class overrides a function of ThreadLocal 3:

    /**
     * 该函数在父线程创建子线程,向子线程复制InheritableThreadLocal变量时使用
     */
    protected T childValue(T parentValue) {
        return parentValue;
    }
    /**
     * 由于重写了getMap,操作InheritableThreadLocal时,
     * 将只影响Thread类中的inheritableThreadLocals变量,
     * 与threadLocals变量不再有关系
     */
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }
    /**
     * 类似于getMap,操作InheritableThreadLocal时,
     * 将只影响Thread类中的inheritableThreadLocals变量,
     * 与threadLocals变量不再有关系
     */
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }

Note: Due to the rewrite the getMap () and CreateMap () two functions, so when

4, the threads pass value realization principle

Speaking InheritableThreadLocal, but also from the Thread class:

public class Thread implements Runnable { ......(其他源码) /* * 当前线程的ThreadLocalMap,主要存储该线程自身的ThreadLocal */ ThreadLocal.ThreadLocalMap threadLocals = null; /* * InheritableThreadLocal,自父线程集成而来的ThreadLocalMap, * 主要用于父子线程间ThreadLocal变量的传递 * 本文主要讨论的就是这个ThreadLocalMap */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; ......(其他源码) } 

Thread class contains  threadLocals  and  inheritableThreadLocals  two variables, i.e., wherein the primary storage inheritableThreadLocals automatically transferred to the sub-thread ThreadLocal.ThreadLocalMap.
Then look at the parent thread child thread creation process, we start with the most simple way:

4.1, the user creates Thread

Thread thread = new Thread();

4.2, Thread creation

    /**
     * Allocates a new {@code Thread} object. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, null, gname)}, where {@code gname} is a newly generated
     * name. Automatically generated names are of the form
     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
     */
    public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } 

4.3, Thread initialization

    /**
     * 默认情况下,设置inheritThreadLocals可传递
     */
    private void init(ThreadGroup g, Runnable target, String name, long stackSize) { init(g, target, name, stackSize, null, true); } 
    /**
     * 初始化一个线程.
     * 此函数有两处调用,
     * 1、上面的 init(),不传AccessControlContext,inheritThreadLocals=true
     * 2、传递AccessControlContext,inheritThreadLocals=false
     */
    private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { ......(其他代码) if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); ......(其他代码) } 

It can be seen that, when the default mode is generated child thread, inheritThreadLocals = true; At this time, if the parent thread inheritableThreadLocals empty, the parent thread inheritableThreadLocals not transmitted to the sub-thread.

4.4、ThreadLocal.createInheritedMap

Let us continue to follow createInheritedMap:

    static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
        return new ThreadLocalMap(parentMap);
    }
        /**
         * 构建一个包含所有parentMap中Inheritable ThreadLocals的ThreadLocalMap
         * 该函数只被 createInheritedMap() 调用.
         */
        private ThreadLocalMap(ThreadLocalMap parentMap) { Entry[] parentTable = parentMap.table; int len = parentTable.length; setThreshold(len); // ThreadLocalMap 使用 Entry[] table 存储ThreadLocal table = new Entry[len]; // 逐一复制 parentMap 的记录 for (int j = 0; j < len; j++) { Entry e = parentTable[j]; if (e != null) { @SuppressWarnings("unchecked") ThreadLocal<Object> key = (ThreadLocal<Object>) e.get(); if (key != null) { // 可能会有同学好奇此处为何使用childValue,而不是直接赋值, // 毕竟childValue内部也是直接将e.value返回; // 个人理解,主要为了减轻阅读代码的难度 Object value = key.childValue(e.value); Entry c = new Entry(key, value); int h = key.threadLocalHashCode & (len - 1); while (table[h] != null) h = nextIndex(h, len); table[h] = c; size++; } } } } 

From ThreadLocalMap it found that the child thread one by one copy of all records parentMap to own thread.

5, summary

When InheritableThreadLocal mainly used for child thread created, you need to automatically inherit parent thread ThreadLocal variable, to facilitate further transfer the necessary information.

Guess you like

Origin www.cnblogs.com/kelelipeng/p/11613998.html