上网查看了很多篇 ThreadLocal 的原理的博客,上来都是文字一大堆,费劲看了半天,大脑中也没有一个模型,想着要是能够有一张图明确表示出来 ThreadLocal 的设计该多好,所以就自己看了源码,画了一张图出来,立刻清晰不少。
- 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();
- }
- ThreadLocalMap getMap(Thread t) {
- return t.threadLocals;
- }
- 1 ThreadLocal.ThreadLocalMap threadLocals = null;
- private Entry getEntry(ThreadLocal<?> key) {
- int i = key.threadLocalHashCode & (table.length - 1);
- Entry e = table[i];
- if (e != null && e.get() == key)
- return e;
- else
- return getEntryAfterMiss(key, i, e);
- }
通过上面的代码可以看出来,在每个线程里面都保存了 ThreadLocalMap,而 ThreaLocalMap 里面又存储了以 ThreadLocal 为键值的 Entry 数组。
用一张图来表示更清楚
先看 ThreadLocal 的 set 方法,我们看一下 ThreatLocal 具体是怎么操作的
- public void set(T value) {
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);
- if (map != null)
- map.set(this, value);
- else
- createMap(t, value);
- }
- void createMap(Thread t, T firstValue) {
- t.threadLocals = new ThreadLocalMap(this, firstValue);
- }
通过上面的代码可以看出来 ThreadLocal 的存储
1、 获取当前线程
2、 获取到当前线程中的 ThreadLocalMap
3、 如果获取到的 ThreadLocalMap 不为 null,就以当前 ThreadLocal 对象为键,以要插入的值为值,ThreadMapLocalMap 中。
4、 如果获取的的 ThreadLocalMap 为 null,则创建一个 ThreadLocalMap 对象
- 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();
- }
- private T setInitialValue() {
- T value = initialValue();
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);
- if (map != null)
- map.set(this, value);
- else
- createMap(t, value);
- return value;
- }
通过上面的代码可以看出来 ThreadLocal 的 Get 步骤为
1、 获取当前线程
2、 根据当前线程获取线程中的 ThreadLocalMap
3、 如果获取到的 ThreadLocalMap 不为 null, 则以当前 ThreadLocal 为键,获取存储在 ThreadLocalMap 中的值并返回
4、 如果获取到的 ThreadLocalMap 为 null,则创建一个以当前对象为键的对象,以 ThreadLocal 设置的初始值为值,存入 ThreadLocalMap 中,然后返回。
- protected T initialValue() {
- return null;
- }
上面这个 initalValue 方法是在创建 ThreadLocalMap 时候的 value 值的默认初始值,代码中默认返回的是 null,我们可以通过自己在代码中自己设计值。
来源: http://www.cnblogs.com/fhhk/p/7384545.html