博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Understanding ThreadLocal And InheritableThreadLocal
阅读量:6573 次
发布时间:2019-06-24

本文共 4061 字,大约阅读时间需要 13 分钟。

hot3.png

Use ThreadLocal Example

// create static global reference s1(type: ThreadLocal)public static ThreadLocal
s1 = new ThreadLocal
();// then set value in thread (just which thread run it)s1.set("value");// then you can get the value where the thread is running s1.get();//在线程池环境中需要手动移除它,(线程终止会自动移除ThreadLocal,但线程池的线程还会继续使用)s1.remove()

The Magic of ThreadLocal

只有一个静态引用(s1),但是却可以在不同的线程中取到不同的值,why?

先看一下 set 方法

public void set(T value) {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);  //从这里可以看出 每个线程对应一个 ThreadLocalMap         if (map != null)            map.set(this, value);        else            createMap(t, value);    }// 先来看初次赋值void createMap(Thread t, T firstValue) {        t.threadLocals = new ThreadLocalMap(this, firstValue); // threadLocals 线程的内部变量    }// ThreadLocalMap 的构造方法ThreadLocalMap(ThreadLocal
firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); }
  1. 每个线程对应一个 ThreadLocalMap
  2. ThreadLocalMap的key 的值就是 ThreadLocal 本身(s1),value 就是 set 传入的值

我们再来看一下 get 方法

public T get() {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        if (map != null) {            ThreadLocalMap.Entry e = map.getEntry(this);  //取出(s1)对应的值            if (e != null) {                @SuppressWarnings("unchecked")                T result = (T)e.value;                return result;            }        }        return setInitialValue();    }ThreadLocalMap getMap(Thread t) {        return t.threadLocals;    }

get 方法就是简单的取值

Deep In TheadLocal (weakReference and weakHashMap)

我们从上面知道 ThreadLocalMap 是线程存储ThreadLocal的地方,它类似于WeakHashMap:

/**         * The entries in this hash map extend WeakReference, using         * its main ref field as the key (which is always a         * ThreadLocal object).  Note that null keys (i.e. entry.get()         * == null) mean that the key is no longer referenced, so the         * entry can be expunged from table.  Such entries are referred to         * as "stale entries" in the code that follows.         */        static class Entry extends WeakReference
> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal
k, Object v) { super(k); value = v; } }

上面我们看到,entry 的key 存储的是ThreadLocal (s1)的应用,但是这个引用是个弱引用:

key -------(弱引用)----->> ThreadLocal Instance <<------强引用 -------s1

所以如果 s1=null,那么 ThreadLocal Instance 是会被回收的

so why we should use WeakReference?

InheritableThreadLocal

作用就是在子进程中可以取到父进程的ThreadLocal的值。

/*     * InheritableThreadLocal values pertaining to this thread. This map is     * maintained by the InheritableThreadLocal class.     */    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

InheritableThreadLocal 也只是存储在 ThreadLocalMap 里的

InheritableThreadLocal which subclasses ThreadLocal class is used in such situations. This class has only one method 'protected Object childValue(Object parentValue)' which is used to set the initial value of the InheritableThreadLocal variable in the child thread as a function of a ThreadLocal variable (passed as a parameter) in the parent thread. This method is called from within the parent thread before the child thread is created and the default implementation will make the child values identical to parent's, but we can override the childValue() method to set the child value as a function of the parent value for those ThreadLocals which have values in the parent thread. By default the childValue() returns the same input argument, but again an override of the childValue method might change this behavior as well.

唯一的疑问就是什么时候给子线程的inheritableThreadLocals 变量赋的值,就是在父进程创建子进程的时候 调用的 childValue(Object parentValue) 方法。

More

思考:涉及到线程池 和异步操作的时候要怎么传递ThreadLocal?

参考:

转载于:https://my.oschina.net/tigerlene/blog/732397

你可能感兴趣的文章
Java 进阶基础知识
查看>>
我的前端笔记之 meta 篇
查看>>
Python开源软件大全(内附源码)
查看>>
一个故事告诉你什么是消息队列
查看>>
【面经】记一次字节跳动后端面试经历
查看>>
git常用命令(史上最经典)
查看>>
(六)java版电子商务spring cloud分布式微服务b2b2c社交电商- commonservice-config配置服务搭建...
查看>>
ld framework not found "FileProvider" for architecture x86_64 报错
查看>>
@ModelAttribute注解使用
查看>>
如何写出让同事膜拜的漂亮代码?
查看>>
Python爬虫你需要积累这些基本知识_Python学习基础路线
查看>>
Unity(TransForm)
查看>>
Netty 源码深度解析(九) - 编码
查看>>
Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
查看>>
打包设置
查看>>
java B2B2C springmvc mybatis多租户电子商城系统 (七)springboot开启声明式事务
查看>>
(一)springmvc+mybatis+dubbo+zookeeper分布式架构 整合 - 平台导语简介
查看>>
网站模拟登录
查看>>
网卡驱动升级
查看>>
Oracle 常用函数
查看>>