java中ThreadLocal的简单理解

ThreadLocal

  • 从JDK1.2版本开始提供了ThreadLocal类,以一种新的思路解决多线程并发问题。使用ThreadLocal实例维护多线程变量时,不会出现线程安全问题。虽然多个线程共用一个ThreadLocal实例,但在变量的使用上,各线程之间对变量不可见。

ThreadLocal的使用

ThreadLocal threadLocal = new ThreadLocal();

  • ThreadLocal提供无参的构造函数进行实例创建。在使用方面,该类也仅提供了几个简单的方法进行操作:

    1. set方法:threadLocal.set("threadLocal test")对ThreadLocal进行值得设置。
    2. get方法:Object test = threadLocal.get()进行值得获取。
    3. remove方法:threadLocal.remove();删除对应线程中存储的值。
  • 在JDK1.5版本开始,ThreadLocal提供泛型的支持,在获取值时不再需要需要进行类型强转。

ThreadLocal<String> threadLocal = new ThreadLocal();
threadLocal.set("threadLocal test");
String test = threadLocal.get();

源码浅析

  • 通过构造函数我们发现,ThreadLocal在构造函数中并没有做任何操作,所以我们从set方法作为入口进行分析。
public void set(T value) {
  Thread t = Thread.currentThread();
  ThreadLocalMap map = getMap(t);
 if (map != null)
    map.set(this, value);
 else  
   createMap(t, value);
}

通过set方法我们可以看到,ThreadLocal实际是在其内部维护了一个ThreadLocalMap实例进行变量的存储,并把该实例与线程进行绑定。在ThreadLocalMap中key的值为this,也就是当前线程的ThreadLocal实例,value为当前设置的值

  • 在get方法中,通过调用ThreadLocalMap map = getMap(t);获取当前线程绑定的ThreadLocalMap实例,并获取value值。

  • 值得注意的是ThreadLocal同一线程只能存储一个值,如果需要存储多个值,可以考虑封装成一个对象进行存储。

默认值

  • ThreadLocal通过protected T initialValue()方法进行value的初始化。
protected T initialValue() {
    return null;
}

  • 通过源码我们可以看到,该方法直接返回null。所以在创建实例后直接调用get方法时,我们得到的是空值。如果我们需要在ThreadLocal实例创建的时候进行初始化,可以通过继承ThreadLocal并重写initialValue()方法即可。
  • 那么initialValue()方法在何时进行调用的呢?通过查找源码我们在get方法中看到了该方法的调用。
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(); 
  • 通过get方法执行流程可以看到,当ThreadLocal创建实例的时候,ThreadLocalMap map = getMap(t);返回的map值肯定为空,所以执行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;
}
  • 从setInitialValue方法实现可以看到,在该方法中调用了initialValue返回了我们自定义的返回值,并设置到ThreadLocalMap实例中。

  • 通过上面的查看源码可以发现,ThreadLocal在设置初始化值时,需要在第一次调用get方法时才会进行初始化,而不是在实例创建的时候进行初始化。

以上即为个人对ThreadLocal的简单理解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容