前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

ITL

原创
作者头像
用户7133283
修改2021-02-04 17:58:47
5360
修改2021-02-04 17:58:47
举报
文章被收录于专栏:codetang

https://www.cnblogs.com/hama1993/p/10400265.html

基本使用

代码语言:txt
复制
        ThreadLocal<String> threadLocal=new ThreadLocal();
        InheritableThreadLocal<String> inheritableThreadLocal=new InheritableThreadLocal<>();
        threadLocal.set("father threadLocal");
        inheritableThreadLocal.set("father inheritableThreadLocal");
        Thread thread= new Thread(()->{
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //子线程通过TL对象在自己的TLMap中没有找到相关的对象:输出null
            System.out.println("子线程获取父类threadLocal数据:"+threadLocal.get());
            System.out.println("子线程获取父类inheritableThreadLocal数据:"+inheritableThreadLocal.get());
        });
        inheritableThreadLocal.set("father inheritableThreadLocal is change");

        thread.start();
代码语言:txt
复制
子线程获取父类threadLocal数据:null
子线程获取父类inheritableThreadLocal数据:father inheritableThreadLocal

基本原理

set

代码语言:txt
复制
    // TL的set方法,如果是子类的实现,那么获取(getMap)和初始化赋值(createMap)都是ITL对象里的方法
    // 其余操作不变(因为hash计算、查找、扩容都是TLMap里需要做的,这里子类ITL只起到一个为Thread对象里哪个TLMap属性赋值的作用)
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocal.ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

    // ITL里getMap方法的实现
    ThreadLocal.ThreadLocalMap getMap(Thread t) {
        return t.inheritableThreadLocals; //返回的其实是Thread对象的inheritableThreadLocals属性
    }

    // ITL里createMap方法的实现
    void createMap(Thread t, T firstValue) {
        // 也是给Thread的inheritableThreadLocals属性赋值
        t.inheritableThreadLocals = new ThreadLocal.ThreadLocalMap(this, firstValue);
    }

init

代码语言:txt
复制
// 初始化一个Thread对象时的代码段(Thread类的init方法)
Thread parent = currentThread();
if (parent.inheritableThreadLocals != null){ //可以看到,如果父线程存在inheritableThreadLocals的时候,会赋值给子线程(当前正在被初始化的线程)
    // 利用父线程的TLMap对象,初始化一个TLMap,赋值给自己的inheritableThreadLocals(这就意味着这个TLMap里的值会一直被传递下去)
    this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
}

// 看下TL里对应的方法
static ThreadLocal.ThreadLocalMap createInheritedMap(ThreadLocal.ThreadLocalMap parentMap) {
    return new ThreadLocal.ThreadLocalMap(parentMap); //这里就开始初始化TLMap对象了
}

// 根据parentMap来进行初始化子线程的TLMap对象
private ThreadLocalMap(ThreadLocal.ThreadLocalMap parentMap) {
    ThreadLocal.ThreadLocalMap.Entry[] parentTable = parentMap.table; //拿到父线程里的哈希表
    int len = parentTable.length;
    setThreshold(len); // 设置阈值(具体方法参考上一篇)
    table = new ThreadLocal.ThreadLocalMap.Entry[len];

    for (int j = 0; j < len; j++) {
        ThreadLocal.ThreadLocalMap.Entry e = parentTable[j]; //将父线程里的Entry取出
        if (e != null) {
            @SuppressWarnings("unchecked")
            ThreadLocal<Object> key = (ThreadLocal<Object>) e.get(); //获取key
            if (key != null) {
                Object value = key.childValue(e.value); //获取value
                ThreadLocal.ThreadLocalMap.Entry c = new ThreadLocal.ThreadLocalMap.Entry(key, value); //根据k-v重新生成一个Entry
                int h = key.threadLocalHashCode & (len - 1); //计算哈希值
                while (table[h] != null)
                    h = nextIndex(h, len); //线性探查解决哈希冲突问题(具体方法参考上一篇)
                table[h] = c; //找到合适的位置后进行赋值
                size++;
            }
        }
    }
}

// ITL里的childValue的实现
protected T childValue(T parentValue) {
    return parentValue; //直接将父线程里的值返回
}

注意事项

线程安全问题

  • 与父线程共享变量
  • 在线程池中:一个线程会处理多个任务,那么TLMap中数据对每个任务都是可见的

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本使用
  • 基本原理
    • set
      • init
      • 注意事项
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档