一步一步学多线程-ThreadLocal源码解析

  上网查看了很多篇ThreadLocal的原理的博客,上来都是文字一大堆,费劲看了半天,大脑中也没有一个模型,想着要是能够有一张图明确表示出来ThreadLocal的设计该多好,所以就自己看了源码,画了一张图出来,立刻清晰不少。

根据源码代码理清ThreadLocal结构

 1 public T get() {
 2     Thread t = Thread.currentThread();
 3     ThreadLocalMap map = getMap(t);
 4     if (map != null) {
 5         ThreadLocalMap.Entry e = map.getEntry(this);
 6         if (e != null) {
 7             @SuppressWarnings("unchecked")
 8             T result = (T)e.value;
 9             return result;
10         }
11     }
12     return setInitialValue();
13 }
1 ThreadLocalMap getMap(Thread t) {
2     return t.threadLocals;
3 }
1 ThreadLocal.ThreadLocalMap threadLocals = null;
1 private Entry getEntry(ThreadLocal<?> key) {
2     int i = key.threadLocalHashCode & (table.length - 1);
3     Entry e = table[i];
4     if (e != null && e.get() == key)
5         return e;
6     else
7         return getEntryAfterMiss(key, i, e);
8 }

  通过上面的代码可以看出来,在每个线程里面都保存了ThreadLocalMap,而ThreaLocalMap里面又存储了以ThreadLocal为键值的Entry数组。

  用一张图来表示更清楚

      

ThreatLocal的Set步骤 

  先看ThreadLocal的set方法,我们看一下ThreatLocal具体是怎么操作的

1 public void set(T value) {
2     Thread t = Thread.currentThread();
3     ThreadLocalMap map = getMap(t);
4     if (map != null)
5         map.set(this, value);
6     else
7         createMap(t, value);
8 }
1 void createMap(Thread t, T firstValue) {
2     t.threadLocals = new ThreadLocalMap(this, firstValue);
3 }

  通过上面的代码可以看出来ThreadLocal的存储

  1、  获取当前线程

  2、  获取到当前线程中的ThreadLocalMap

  3、  如果获取到的ThreadLocalMap不为null,就以当前ThreadLocal对象为键,以要插入的值为值,ThreadMapLocalMap中。

  4、  如果获取的的ThreadLocalMap为null,则创建一个ThreadLocalMap对象

ThreadLocal的Get步骤

  

 1 public T get() {
 2     Thread t = Thread.currentThread();
 3     ThreadLocalMap map = getMap(t);
 4     if (map != null) {
 5         ThreadLocalMap.Entry e = map.getEntry(this);
 6         if (e != null) {
 7             @SuppressWarnings("unchecked")
 8             T result = (T)e.value;
 9             return result;
10         }
11     }
12     return setInitialValue();
13 }
 1 private T setInitialValue() {
 2     T value = initialValue();
 3     Thread t = Thread.currentThread();
 4     ThreadLocalMap map = getMap(t);
 5     if (map != null)
 6         map.set(this, value);
 7     else
 8         createMap(t, value);
 9     return value;
10 }

  通过上面的代码可以看出来ThreadLocal的Get步骤为

  1、  获取当前线程

  2、  根据当前线程获取线程中的ThreadLocalMap

  3、  如果获取到的ThreadLocalMap不为null,则以当前ThreadLocal为键,获取存储在ThreadLocalMap中的值并返回

  4、  如果获取到的ThreadLocalMap为null,则创建一个以当前对象为键的对象,以ThreadLocal设置的初始值为值,存入ThreadLocalMap中,然后返回。

ThreaLocal中的初始值设置

1 protected T initialValue() {
2     return null;
3 }

  上面这个initalValue方法是在创建ThreadLocalMap时候的value值的默认初始值,代码中默认返回的是null,我们可以通过自己在代码中自己设计值。

posted @ 2017-08-17 21:42  一步一步学  阅读(659)  评论(0编辑  收藏  举报