[InheritableThreadLocal] [InheritableThreadLocal] [InheritableThreadLocal] [InheritableThreadLocal] [InheritableThreadLocal]

Why upgrade

First of all, why upgrade? Which brings us to the functionality of ThreadLocal.

As we know, ThreadLocal is designed to have its own copy for each thread in a multi-threaded environment, which can solve the problem of concurrent modification of multiple threads to some extent. However, we can make an extension of this, such as context. We can use ThreadLocal to have its own context for each thread, usually written as ThreadLocal, so that all changes made on this thread can be used by everyone.

Now, suppose we create a new child thread, can that child thread get the parent thread’s context? In theory you want to achieve this effect, but in practice? Let’s see:

public class ThreadLocalContext { private static ThreadLocal<Context> context = new ThreadLocal<>(); static class Context { String name; int value; } public static void main(String[] args) { Context context = new Context(); context.name = "mainName"; context.value = 10; ThreadLocalContext.context.set(context); Thread childThread = new Thread( new Runnable() { @Override public void run() { Context childContext = ThreadLocalContext.context.get(); System.out.println(childContext.name); System.out.println(childContext.value); }}); childThread.start(); }}Copy the code

After running main, throwing an error directly into the child thread is what we expect, but what if we want the child thread to get the parent thread’s context?

The first thing that comes to mind is to pass the parent ThreadLocal value to the child when the child thread is generated. This works, but the process is cumbersome and the code is intrusive.

At this point you can use InheritableThreadLocal.

What is a InheritableThreadLocal

Look at the source code

Let’s have a look at its source code, we do not be afraid, its source code is very few:

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); }}Copy the code

First, it inherits from ThreadLocal, so it is actually an extended version of ThreadLocal. Next, there are three methods, all of which exist in ThreadLocal.

    T childValue(T parentValue) {
        throw new UnsupportedOperationException();
    }

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

    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }Copy the code

Except that the childValue method throws an exception in ThreadLocal, the other two methods are pretty much the same in both classes, just for different objects. But is the ThreadLocal threadLocals and inheritableThreadLocals. ThreadLocalMap type, this is said in the previous article, is a key for the Entry of a weak reference, this is not the point.

When inheritableThreadLocals is initialized

private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {// omit irrelevant code... Thread parent = currentThread(); . // omit irrelevant code... if (parent.inheritableThreadLocals ! = null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); . }Copy the code

When we generate a child Thread by calling the Thread constructor from the parent Thread, its constructor will eventually call this init method. InheritableThreadLocals is the inheritableThreadLocals from the parent thread, That explains why inheritableThreadLocals supports using variables stored in the parent thread in child threads.

How to use

[InheritableThreadLocal] [InheritableThreadLocal] [InheritableThreadLocal]

public class ThreadLocalContext { private static InheritableThreadLocal<Context> context = new InheritableThreadLocal<>(); static class Context { String name; int value; } public static void main(String[] args) { Context context = new Context(); context.name = "mainName"; context.value = 10; ThreadLocalContext.context.set(context); Thread childThread = new Thread( new Runnable() { @Override public void run() { Context childContext = ThreadLocalContext.context.get(); System.out.println(childContext.name); System.out.println(childContext.value); }}); childThread.start(); }}Copy the code

When run, not only does it not throw an exception, but it outputs the value set by the parent thread in the child thread. Everybody’s happy!

conclusion

InheritableThreadLocal is shared today, mainly because I heard others talking about it in ctrip’s sharing session on Wednesday. The speaker mentioned a more common problem that if we use thread pool to submit tasks, threads in the thread pool will execute tasks, How to get the context of the thread submitting the task is to use Ali’s open source component TTL, which I will describe later.

It has been one month since I joined Ctrip. Although I feel that there are many disadvantages in large companies, such as difficult communication, there are also many advantages, such as technology sharing meetings. Although I took a break from busy time to attend them, I feel good to have more opportunities to learn and communicate about technology.

If you are interested, you can visit my blog or pay attention to my public number and headline number. Maybe there will be unexpected surprises.

death00.github.io/

Public account: The road to health