ThreadLocal的理解

老板提了一个需求,需要我们在某个类中增加一个String成员变量name,好的,没问题

public class A { String name; }

然后老板又提了一个需求,需要增加多一个成员变量data,并且类型不是固定的,OK,很快搞定
那么现在我们会得到个这样的类
public class A { String name; Object data; }

老板:。。。
你:OK
老板:。。。
你:O(**)K
。。。
依此类推,随着情况的变化(成员变量的增多/需要增加n个不定类型/作为一个有上进心得程序猿你决定优化 一下代码/..)等等
你渐渐希望能真正的解决这个问题,最后
public class A { Map data = https://www.it610.com/article/new HashMap(); public Tget(String fieldName){ return data.get(fieldName); } public voidput(String fieldName,Object object){ return data.put(fieldName,object); } }
但你觉得还是不够,每次存储你都要通过fieldName来指定Key,写多了还可能会导致混乱,这个时候杂么办呢?
下面可以通过说明ThreadLocal与Thread的关系来提供一些思路
final static ThreadLocal string = new ThreadLocal() { @Override protected String initialValue() { return "我是一个饼"; } };

很多文章将ThreadLocal译为线程本地变量,本质上这种说法没什么问题
但是为了更好的理解ThreadLocal,我暂且称它为,线程动态成员变量。
Thread类维护了一个ThreadLocalMap类型的成员变量(也可以称作为类的本地变量,按我的理解,成员变量也可以认为是类的本地变量)
这个变量可以认为是一个Map集合(非通常意义上的集合)
这个Map的Key是ThreadLocal,值是 String,各个线程实体间的String是独立实例,互不影响
通过以下例子详细说明
在线程中 通过tl.get();
通过ThreadLocal中的getMap(Thread)取出当前线程的ThreadLocalMap
以下是getMap源码
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }

在ThreadLocalMap中,以ThreadLocal为Key,取值,如果有值,返回
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }

如果没有值,通过ThreadLocal的initialValue()创建一个初始值并存入ThreadLocalMap中,并返回该值,以下是ThreadLocal源 码,this代表ThreadLocal实例
private T setInitialValue() { T value = https://www.it610.com/article/initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; } void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }

Key是同一个Key,值不是同一个值,这个值初始都是通过initialValue()的得到的,不同线程间的value互不影响
而在set()的时候,以下是ThreadLocal源码,this代表ThreadLocal实例
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }

以下是测试代码
new Thread("Thread#1") { @Override public void run() { string.set("我是两个饼"); System.out.println("[Thread#1]:" + string.get() + string.get().hashCode()); } }.start(); new Thread("Thread#2") { @Override public void run() { string.set("我是三个饼"); System.out.println("[Thread#2]:" + string.get() + string.get().hashCode()); } }.start(); System.out.println("[Thread#main]:" + string.get() + string.get().hashCode());

打印结果:

ThreadLocal的理解
文章图片
image.png 【ThreadLocal的理解】ThreadLocal的应用可以通过了解Android中的Handler消息机制加深理解

    推荐阅读