> 文章列表 > ThreadLocal原理详解

ThreadLocal原理详解

ThreadLocal就像线程的“专属保险箱”,每个线程都有自己的存储空间,互不干扰。想让多个线程同时操作同一个变量?static变量来帮忙!但要是希望每个线程有自己的“私房钱”,就得靠ThreadLocal了。

比如,银行的每个柜台都有一个专门的窗口,只处理自己的客户,ThreadLocal就相当于每个窗口的专属抽屉,其他人进不来。

不过,你得注意这个“保险箱”可不是免费的午餐,用完得记得清理,不然内存可要吃不消了!想知道怎么正确使用它,避免内存泄漏?我下次告诉你。

对了,想不想知道哪些框架也在用这个“黑科技”?下次聊!

ThreadLocal原理详解

1.概述

我们知道,想要实现变量共享,可以采取定义static修饰的类变量(静态变量)的形式,所有的线程共享这个变量。但是现在,我们想要实现每个线程独享这个变量,应该怎么实现呢?

2.什么是ThreadLocal

于是乎,ThreadLocal出现了。它实现了线程与线程之间的数据的隔离,互不干扰。那么ThreadLocal到底是何方神圣呢?

ThreadLocal是用来管理线程的私有数据,使得线程对该数据的操作对其他线程不可见,达到数据隔离的效果。

那么,Java中是怎么实现这种机制的呢?接下来一一揭晓。

2.1 Thread、ThreadLocal、ThreadLocalMap三剑客

ThreadLocal中定义了内部类ThreadLocalMapThreadLocalMap类似于HashMap,其中keyThreadLocalvalue为想要存储的值。然后呢,每个Thread对象中维护了一个ThreadLocalMap,因此,每个线程都可以很方便的访问只属于自己的数据。

我们通过源代码来跟踪一下Thread、ThreadLocal、ThreadLocalMap三者之间的联系。

ThreadLocal.java

// ThreadLocal.java
public class ThreadLocal {// 静态内部类static class ThreadLocalMap {}
}

Thread.java

// Thread.java
public class Thread {ThreadLocal.ThreadLocalMap threadLocals = null;
}

那么,它们三者的关系呢就像下面这张图一样:

  • 人(Thread):当前线程对象。
  • 公文包(ThreadLocalMap):属于当前线程对象,用于存放只能由当前线程访问的数据。
  • 文件(ThreadLocal):文件的key为ThreadLocal对象

ThreadLocal原理详解
再来看看它们的数据结构:

ThreadLocal原理详解

3.ThreadLocal的作用

先来体验一下ThreadLocal的API:

public class ThreadLocalTest {private static ThreadLocal<String> threadLocal = new ThreadLocal<>();public static void main(String[] args) {System.out.println(threadLocal.get());threadLocal.set("one and only");System.out.println(threadLocal.get());}
}

ThreadLocal原理详解

接下来我们来验证一下数据隔离的效果。

import lombok.SneakyThrows;import java.util.concurrent.TimeUnit;public class ThreadLocalTest {private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();@SneakyThrowspublic static void main(String[] args) {Thread threadA = new Thread(() -> {threadLocal.set(Thread.currentThread().getName());System.out.println(Thread.currentThread().getName() + "完成了签名")