面试官:小伙子,听说你看过 ThreadLocal 源码?(万字图文深度解析)

作者:微信小助手

发布时间:2020-05-11T13:12:49

首先贴出一张图:


前几天写了一篇AQS相关的文章:我画了35张图就是为了让你深入 AQS,反响不错,还上了博客园首页编辑推荐,有生之年系列呀,哈哈。

image.png

这次趁热打铁再写一篇ThreadLocal的文章,同样是深入原理,图文并茂。

全文共10000+字,31张图,这篇文章同样耗费了不少的时间和精力才创作完成,原创不易,请大家多多关注我的公众号壹枝花算不算浪漫,感谢。

对于ThreadLocal,大家的第一反应可能是很简单呀,线程的变量副本,每个线程隔离。那这里有几个问题大家可以思考一下:

  • ThreadLocal的key是弱引用,那么在 threadLocal.get()的时候,发生GC之后,key是否为null

  • ThreadLocalThreadLocalMap数据结构

  • ThreadLocalMapHash算法

  • ThreadLocalMapHash冲突如何解决?

  • ThreadLocalMap扩容机制?

  • ThreadLocalMap中过期key的清理机制?探测式清理启发式清理流程?

  • ThreadLocalMap.set()方法实现原理?

  • ThreadLocalMap.get()方法实现原理?

  • 项目中ThreadLocal使用情况?遇到的坑?

  • ……

上述的一些问题你是否都已经掌握的很清楚了呢?本文将围绕这些问题使用图文方式来剖析ThreadLocal点点滴滴

全文目录

  1. ThreadLocal代码演示

  2. ThreadLocal的数据结构

  3. GC 之后key是否为null

  4. ThreadLocal.set()方法源码详解

  5. ThreadLocalMap Hash算法

  6. ThreadLocalMap Hash冲突

  7. ThreadLocalMap.set()详解
    7.1 ThreadLocalMap.set()原理图解
    7.2 ThreadLocalMap.set()源码详解

  8. ThreadLocalMap过期key的探测式清理流程

  9. ThreadLocalMap扩容机制

  10. ThreadLocalMap.get()详解
    10.1 ThreadLocalMap.get()图解
    10.2 ThreadLocalMap.get()源码详解

  11. ThreadLocalMap过期key的启发式清理流程

  12. InheritableThreadLocal

  13. 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的数据结构