ThreadLocal

线程共享进程的内存空间,因此线程之间的变量是共享的。ThreadLocal为线程提供一个私有空间,用于存储私有变量。ThreadLocal是如何做到提供私有空间的呢。Read the fucking source code


ThreadLocal_第1张图片
image.png

ThreadLocal 有个静态内部类,ThreadLocalMap。从类名可知,该静态内部类是用于存储数据使用,该静态内部类也有一个 Entry的静态内部类,Entry继承自WeakReference。看到WeakReference我们就能断定,这个Entry是存储数据的单元,并且使用了虚引用,便于垃圾回收器对其进行回收。
Entry类的泛型参数为ThreadLocal,可知该类持有ThreadLocal实例。Entry的构造函数接收两个参数,一个为ThreadLocal 对象,另一个为Object对象。继续看如何使用Entry。


ThreadLocal_第2张图片
image.png

ThreadLocalMap构造器接收两个参数,刚好和Entry一样。构造方法里面,创建了初始大小的Entry数组,并创建了一个Entry对象,赋值给table数组里的某一个。
看一下getEntry方法
ThreadLocal_第3张图片
image.png

该方法根据key的threadLocalHashCode与table长度,寻找到存放在数组里的位置。如果失败,则通过getEntryAfterMiss寻找Entry。具体是如何放置和寻找在table中的位置,由于涉及hashCode,以后有机会再分析。我们记住通过ThreadLocal对象寻找到对应的Entry。

从firstKey,firstValue的字段名称,我们可以猜测,ThreadLocalMap接收key为ThreadLocal对象,值为Object对象的键值对,存储在Entry数组中,该类没有继承自Map类,但也实现了与之类似的功能。接下来我们继续看ThreadLocal是如何使用ThreadLocalMap的。


ThreadLocal_第4张图片
image.png

从ThreadLocal的get方法我们可以看到。先是获取当前线程,然后通过getMap方法获取ThreadLocalMap对象,如果ThreadLocalMap对象存在,则通过map.getEntry(this)获取Entry对象,然后返回放置其中的value。如果ThreadLocalMap对象不存在则调用setInitialValue方法,创建ThreadLocalMap对象,返回initialValue。

ThreadLocal_第5张图片
image.png

继续查看getMap得知,ThreadLocalMap是存放在Thread的threadLocals变量中,而threadLocals变量是在createMap的时候,创建的一个ThreadLocalMap实例。


ThreadLocal_第6张图片
image.png

ThreadLocal_第7张图片
image.png

查看ThreadLocal的set方法,同样通过Thread获取到ThreadLocalMap,并往ThreadLocalMap存放数据。
ThreadLocal_第8张图片
image.png

总结一下:
每一个线程通过threadLocals字段,存放ThreadLocalMap对象,这个threadLocals字段为线程提供了私有空间。可以通过ThreadLocal实例,获取与当前线程关联的ThreadLocalMap对象,从而获取存放的value。
1.通过同一个ThreadLocal实例,在不同线程中set,get,存取在各自线程中的值。
2.通过不同的ThreadLocal实例,在同一线程的ThreadLocalMap中,存放数据在Entry数组的不同位置。

你可能感兴趣的:(ThreadLocal)