InheritableThreadLocal-- 特殊的ThreadLocal

来源:互联网 发布:淘宝国潮模特脖子纹身 编辑:程序博客网 时间:2024/05/18 03:31

ThreadLocal允许我们在线程中保存一些变量,但是做不到父子线程数据的共享

public class InheritThreadLocal {    public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();//    public static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<Integer>();    public static void main(String args[]) throws InterruptedException {        threadLocal.set(new Integer(123));        Thread thread = new MyThread();        thread.start();        Thread hread = new MThread();        hread.start();        System.out.println("main = " + threadLocal.get());    }    static class MyThread extends Thread {        @Override        public void run() {            System.out.println("MyThread = " + threadLocal.get());            new Thread(new Runnable() {                public void run() {                    System.out.println("MyThread son = " + threadLocal.get());                }            }).start();        }    }    static class MThread extends Thread {        @Override        public void run() {            System.out.println("MThread = " + threadLocal.get());        }    }}
如这段代码,执行结果是


为什么子线程拿不到threadlocal中的数据,那是因为:

ThreadLocalMap getMap(Thread t) {    return t.threadLocals;}
子线程拿到的是当前线程的threadlocal,而这个里面没有存储数据。

如果刚才的代码把注释的去掉,把注释下边那一行注释掉,执行结果是


这下子线程拿到threadlocal里面的数据了,这又是为什么呢

原因其实就是InheritableThreadLocal里面

ThreadLocalMap getMap(Thread t) {   return t.inheritableThreadLocals;}
子线程拿到的是继承过来的threadlocal里面的数据,也就是说它拿到了父线程刚才设置的数据,那这个inheritableThreadLocals又是什么时候设置进去的呢

private void init(ThreadGroup g, Runnable target, String name,                  long stackSize) {  .....    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();}
注意if中的代码,创建线程的时候,都会去做这样的判断,如果inheritableThreadLocals里面有数据,就会将它复制到当前的threadlocal中

/** * Construct a new map including all Inheritable ThreadLocals * from given parent map. Called only by createInheritedMap. * * @param parentMap the map associated with parent thread. */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) {            ThreadLocal key = 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++;            }        }    }}

这下就明白了,如果是InheritableThreadLocal,它重写了Threadlocal中的getMap方法(上边贴代码了),在这个里面,它会拿到父线程threadlocal中的数据。

InheritableThreadLocal适用于子线程需要父线程中数据的情况


原创粉丝点击