InheritableThreadLocal-- 特殊的ThreadLocal

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适用于子线程需要父线程中数据的情况


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值