[Concurrent programming] ThreadLocal brother InheritableThreadLocal


This blog series is to learn the process of recording concurrent programming summarized. As more articles written by time is relatively loose, so I put together a catalog paste (portal) for easy access.

Concurrent Programming Series blog portal


Primer

public class InheritableThreadLocalDemo {

    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        threadLocal.set("mainThread");
        System.out.println("value:"+threadLocal.get());
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                String value = threadLocal.get();
                System.out.println("value:"+value);
            }
        });
        thread.start();
    }

}

The above code is provided a ThreadLocal variable in the main thread, and set its value mainThread. Then there opens up a child thread in the main thread thread, and trying to get the value of ThreadLocal variables set in the main thread. But the results are as follows:

value:mainThread
value:null

Introduced by the previous article, we will respect the result of the above is very easy to understand. Each thread has its own ThreadLocalMap, so the child thread calling the get method to get the value when in fact visit is his ThreadLocalMap, Map and Map this main thread are two different objects, so definitely get value of.

So there is no similar Java objects to achieve the above functions? There, InheritableThreadLocalyou can achieve this function, this class allows ThreadLocal value sub-thread inherits parent thread has been set.

InheritableThreadLocal simple to use

Or in the above Liezi column, we just need to become ThreadLocal InheritableThreadLocal on the line.

public class InheritableThreadLocalDemo {

    private static InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();

    public static void main(String[] args) {
        threadLocal.set("mainThread");
        System.out.println("value:"+threadLocal.get());
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                String value = threadLocal.get();
                System.out.println("value:"+value);
            }
        });
        thread.start();
    }

}

Execution results are as follows:

value:mainThread
value:mainThread

InheritableThreadLocal Principle Analysis

InheritableThreadLocal look at the source code:

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
   
    protected T childValue(T parentValue) {
        return parentValue;
    }

   
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }

  
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }
}

This class extends ThreadLocal, and rewrote getMap and createMap method, the difference is in the ThreadLocal threadLocals replaced inheritableThreadLocals, these two variables are ThreadLocalMap type, and are property of the Thread class.

Here's a step by step look at how to get InheritableThreadLocal ThreadLocal value in the parent thread.

step1: InheritableThreadLocal first call to get the value of the get method, so we get a direct look at methods to do some Han.

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

As can be seen from the above code, and ThreadLocal GET method is the same, the only difference is a method wherein the getMap rewritten, returns inheritableThreadLocals properties. This property is also a ThreadLocalMap types of variables. Well, from here on it can be inferred: definitely somewhere assigning values ​​ThreadLocal parent thread to inheritableThreadLocals child thread.

step2: Search what areas to use the source code inheritableThreadLocalsto this property, and finally found the code:

private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        this.name = name.toCharArray();
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            if (security != null) {
                g = security.getThreadGroup();
            }
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
        g.checkAccess();
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }
        g.addUnstarted();
        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        //1. 这边先判断了父线程中inheritableThreadLocals属性是否为空,不为空的话就复制给子线程
        if (parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

The code above confirms our conjecture. Note that once the child thread is created, then operate the parent thread ThreadLocal variable, then the child thread is imperceptible. Father and child thread or threads have their own ThreadLocalMap, just create a sub-thread "moment" to copy the parent thread to child thread ThreadLocalMap, both will have nothing to follow up.

Guess you like

Origin www.cnblogs.com/54chensongxia/p/12015443.html