(高清无损原图.pdf关注公众号后回复 ThreadLocal 获取,文末有公众号链接)
前几天写了一篇AQS相关的文章:我画了35张图就是为了让你深入 AQS,反响不错,还上了博客园首页编辑推荐,有生之年系列呀,哈哈。
image.png这次趁热打铁再写一篇ThreadLocal的文章,同样是深入原理,图文并茂。
全文共10000+字,31张图,这篇文章同样耗费了不少的时间和精力才创作完成,原创不易,请大家点点关注+在看,感谢。
对于ThreadLocal,大家的第一反应可能是很简单呀,线程的变量副本,每个线程隔离。那这里有几个问题大家可以思考一下:
ThreadLocal的key是弱引用,那么在 threadLocal.get()的时候,发生GC之后,key是否为null?
ThreadLocal中ThreadLocalMap的数据结构?
ThreadLocalMap的Hash算法?
ThreadLocalMap中Hash冲突如何解决?
ThreadLocalMap扩容机制?
ThreadLocalMap中过期key的清理机制?探测式清理和启发式清理流程?
ThreadLocalMap.set()方法实现原理?
ThreadLocalMap.get()方法实现原理?
项目中ThreadLocal使用情况?遇到的坑?
……
上述的一些问题你是否都已经掌握的很清楚了呢?本文将围绕这些问题使用图文方式来剖析ThreadLocal的点点滴滴。
全文目录
ThreadLocal代码演示
ThreadLocal的数据结构
GC 之后key是否为null?
ThreadLocal.set()方法源码详解
ThreadLocalMap Hash算法
ThreadLocalMap Hash冲突
ThreadLocalMap.set()详解
7.1 ThreadLocalMap.set()原理图解
7.2 ThreadLocalMap.set()源码详解
ThreadLocalMap过期key的探测式清理流程
ThreadLocalMap扩容机制
ThreadLocalMap.get()详解
10.1 ThreadLocalMap.get()图解
10.2 ThreadLocalMap.get()源码详解
ThreadLocalMap过期key的启发式清理流程
InheritableThreadLocal
ThreadLocal项目中使用实战
13.1 ThreadLocal使用场景
13.2 分布式TraceId解决方案
注明: 本文源码基于JDK 1.8
ThreadLocal代码演示我们先看下ThreadLocal使用示例:
public class ThreadLocalTest {private List<String> messages = Lists.newArrayList();
public static final ThreadLocal<ThreadLocalTest> holder = ThreadLocal.withInitial(ThreadLocalTest::new);
public static void add(String message) {
holder.get().messages.add(message);
}
public static List<String> clear() {
List<String> messages = holder.get().messages;
holder.remove();
System.out.println("size: " + holder.get().messages.size());
return messages;
}
public static void main(String[] args) {
ThreadLocalTest.add("一枝花算不算浪漫");
System.out.println(holder.get().messages);
ThreadLocalTest.clear();
}
}
打印结果:
[一枝花算不算浪漫]size: 0
ThreadLocal对象可以提供线程局部变量,每个线程Thread拥有一份自己的副本变量,多个线程互不干扰。
ThreadLocal的数据结构 image.pngThread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,也就是说每个线程有一个自己的ThreadLocalMap。