三种ThreadLocal详解

ThreadLocal在实际开发中经常被用于存储当前线程上下文信息,如登录用户信息、全局traceId以及一些需要线程间隔离的数据

这篇文章主要是针对ThreadLocal的问题,进行简要分析,以及延伸出来的另外两种跨线程/线程池ThreadLocal简单介绍

ThreadLocal

在Thread对象中有字段 threadLocals(ThreadLocalMap) 用于存储 key(ThreadLocal对象,弱引用) value(ThreadLocal value) 这个map通过线性探测法解决hash冲突问题,每次get/set时可能还伴随着清理掉key为null的entry键值对 主要问题:

  1. 当前线程的ThreadLocal无法透传到子线程或线程池中

  2. 当使用ThreadLocal对象时没有显式remove时,可能导致内存泄露

InheritableThreadLocal

InheritableThreadLocal 子线程在创建时会拷贝父线程中的inheritableThreadLocalMap Entry会重新创建,并插入子线程inheritableThreadLocalMap中,value只是浅拷贝

存在的主要问题:

  1. value为浅拷贝,如果value为对象,在子线程中对value的属性的修改,父线程中也会对应改变

  2. 拷贝过程只会发生在线程创建初始化时,当子线程如果是在线程池中,如果线程复用不会销毁,所以只有在首次创建线程 时才会透传,当线程已全部创建完毕时,InheritableThreadLocal是无法进行透传到线程池中的线程的 代码输出

TransmittableThreadLocal

如果需要将ThreadLocal对象透传到线程池Runnable中使用,需要使用TransmittableThreadLocal

且需要配合TtlRunnable/TtlCallable使用,在原本Runnable中wrap一层

代码实验示例

最后更新于