前言

上篇文章 深入理解 Handler 消息机制 中提到了获取线程的 Looper 是通过 ThreadLocal 来实现的:

public static @Nullable Looper myLooper() {     return sThreadLocal.get(); }

每个线程都有自己的 Looper,它们之间不应该有任何交集,互不干扰,我们把这种变量称为 线程局部变量 。而 ThreadLocal 的作用正是存储线程局部变量,每个线程中存储的都是独立存在的数据副本。如果你还是不太理解,看一下下面这个简单的例子:

public static void main(String[] args) throws InterruptedException {      ThreadLocal<Boolean> threadLocal = new ThreadLocal<Boolean>();     threadLocal.set(true);      Thread t1 = new Thread(() -> {         threadLocal.set(false);         System.out.println(threadLocal.get());     });      Thread t2 = new Thread(() -> {         System.out.println(threadLocal.get());     });      t1.start();     t2.start();     t1.join();     t2.join();     System.out.println(threadLocal.get()); }

执行结果是:

false null true

可以看到,我们在不同的线程中调用同一个 ThreadLocal 的 get() 方法,获得的值是不同的,看起来就像 ThreadLocal 为每个线程分别存储了不同的值。那么这到底是如何实现的呢?一起来看看源码吧。

以下源码基于 JDK 1.8 , 相关文件:

Thread.java

ThreadLocal.java

ThreadLocal

首先 ThreadLocal 是一个泛型类,public class ThreadLocal<T>,支持存储各种数据类型。它对外暴露的方法很少,基本就 get() 、set() 、remove() 这三个。下面依次来看一下。

set()

public void set(T value) {     Thread t = Thread.currentThread();     ThreadLocalMap map = getMap(t); // 获取当前线程的 ThreadLocalMap     if (map != null)         map.set(this, value);     else         createMap(t, value); // 创建 ThreadLocalMap }

这里出现了一个新东西 ThreadLocalMap,暂且就把他当做一个普通的 Map。从 map.set(this, value) 可以看出来这个 map 的键是 ThreadLocal 对象,值是要存储的 value 对象。其实看到这,ThreadLocal 的原理你应该基本都明白了。