InheritableThreadLocal分析

目录

1.简介

2.使用

3.源码分析

3.1.1 ThreadLocal

3.1.2 InheritableThreadLocal

3.1.3Thread.init()

4.总结


1.简介

InheritableThreadLocal作为ThreadLocal的扩展,本身要达到的目的依然是线程局部数据的存储,功能完全等同ThreadLocal,并在其基础上增加了父子线程减数据传递的功能,使用了Thread的另一个变量

ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

在new Thread(Runnable)的时候,会执行init初始化方法,进而将父线程的inheritableThreadLocals数据传递给子线程,详见源码分析第三节。

2.使用

demo

public class MyThread_localThreadTest {

    public static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    public static ThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();

    public static void main(String[] args) {
        threadLocal.set("threadLocal 的值: hello threadLocal");
        inheritableThreadLocal.set("inheritableThreadLocal 的值: hello inheritableThreadLocal");

        new Thread(()-> {
            System.out.println("子线程获取到的值--threadLocal:" + threadLocal.get());
            System.out.println("子线程获取到的值--inheritableThreadLocal:" + inheritableThreadLocal.get());

            System.out.println("==================================");

            new Thread(()->{
                System.out.println("孙子线程获取到的值--threadLocal:" + threadLocal.get());
                System.out.println("孙子线程获取到的值--inheritableThreadLocal:" + inheritableThreadLocal.get());
            }).start();

        }).start();
    }
}

输出:

子线程获取到的值--threadLocal:null
子线程获取到的值--inheritableThreadLocal:inheritableThreadLocal 的值: hello inheritableThreadLocal
==================================
孙子线程获取到的值--threadLocal:null
孙子线程获取到的值--inheritableThreadLocal:inheritableThreadLocal 的值: hello inheritableThreadLocal

 

3.源码分析

3.1.1 ThreadLocal

上篇我们分析了ThreadLocal,点击详细

这里我们着重分析InheritableThreadLocal

3.1.2 InheritableThreadLocal

public class InheritableThreadLocal<T> extends ThreadLocal<T> {

	@Override
    protected T childValue(T parentValue) {
        return parentValue;
    }

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


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

InheritableThreadLocal重写了ThreadLocal的getMap(),createMap()方法,转而使用了新的变量,而在new Thread()时会根据条件初始化该变量

3.1.3Thread.init()

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

继续跟踪ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
    return new ThreadLocalMap(parentMap);
}

而new ThreadLocalMap(parentMap);就是对数据的复制

private ThreadLocalMap(ThreadLocalMap parentMap) {
	Entry[] parentTable = parentMap.table;
	int len = parentTable.length;
	setThreshold(len);
	table = new Entry[len];

	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) {
				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++;
			}
		}
	}
}

 

4.总结

简单明了,但是现目前的项目中,我们更多的使用的是线程池,故而其使用场景不是特别广泛。

上一篇:filter过滤器


下一篇:阿里面试官用HashMap把我问倒了