作者:微信小助手
发布时间:2020-05-11T13:12:49
首先贴出一张图:
前几天写了一篇AQS
相关的文章:我画了35张图就是为了让你深入 AQS,反响不错,还上了博客园首页编辑推荐,有生之年系列呀,哈哈。
这次趁热打铁再写一篇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
使用示例:
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
拥有一份自己的副本变量,多个线程互不干扰。