ThreadLocal详解

ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量。

这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线程都在操作同一个变量,显然是不行的,并且我们也知道volatile这个关键字也是不能保证线程安全的。那么在有一种情况之下,我们需要满足这样一个条件:变量是同一个,但是每个线程都使用同一个初始值,也就是使用同一个变量的一个新的副本。这种情况之下ThreadLocal就非常使用,比如说DAO的数据库连接,我们知道DAO是单例的,那么他的属性Connection就不是一个线程安全的变量。而我们每个线程都需要使用他,并且各自使用各自的。这种情况,ThreadLocal就比较好的解决了这个问题。

我们从源码的角度来分析这个问题。

首先定义一个ThreadLocal:

publicclassConnectionUtil {

privatestaticThreadLocal tl =newThreadLocal();

privatestaticConnection initConn =null;static{try{

initConn= DriverManager.getConnection("url, name and password");

}catch(SQLException e) {

e.printStackTrace();

}

}publicConnection getConn() {

Connection c=tl.get();if(null==c) tl.set(initConn);returntl.get();

}

}

这样子,都是用同一个连接,但是每个连接都是新的,是同一个连接的副本。

那么实现机制是如何的呢?

1、每个Thread对象内部都维护了一个ThreadLocalMap这样一个ThreadLocal的Map,可以存放若干个ThreadLocal。

1

2

3/* ThreadLocal values pertaining to this thread. This map is maintained

* by the ThreadLocal class. */

ThreadLocal.ThreadLocalMap threadLocals =null;

2、当我们在调用get()方法的时候,先获取当前线程,然后获取到当前线程的ThreadLocalMap对象,如果非空,那么取出ThreadLocal的value,否则进行初始化,初始化就是将initialValue的值set到ThreadLocal中。

1

2

3

4

5

6

7

8

9

10publicT get() {

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if(map !=null) {

ThreadLocalMap.Entry e = map.getEntry(this);

if(e !=null)

return(T)e.value;

}

returnsetInitialValue();

}

3、当我们调用set()方法的时候,很常规,就是将值设置进ThreadLocal中。

4、总结:当我们调用get方法的时候,其实每个当前线程中都有一个ThreadLocal。每次获取或者设置都是对该ThreadLocal进行的操作,是与其他线程分开的。

5、应用场景:当很多线程需要多次使用同一个对象,并且需要该对象具有相同初始化值的时候最适合使用ThreadLocal。

6、其实说再多也不如看一下源码来得清晰。如果要看源码,其中涉及到一个WeakReference和一个Map,这两个地方需要了解下,这两个东西分别是a.Java的弱引用,也就是GC的时候会销毁该引用所包裹(引用)的对象,这个threadLocal作为key可能被销毁,但是只要我们定义成他的类不卸载,tl这个强引用就始终引用着这个ThreadLocal的,永远不会被gc掉。b.和HashMap差不多。

事实上,从本质来讲,就是每个线程都维护了一个map,而这个map的key就是threadLocal,而值就是我们set的那个值,每次线程在get的时候,都从自己的变量中取值,既然从自己的变量中取值,那肯定就不存在线程安全问题,总体来讲,ThreadLocal这个变量的状态根本没有发生变化,他仅仅是充当一个key的角色,另外提供给每一个线程一个初始值。如果允许的话,我们自己就能实现一个这样的功能,只不过恰好JDK就已经帮我们做了这个事情。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • ThreadLocal在java.lang包中,其主要作用是提供一个和线程绑定的变量环境,即通过ThreadLoc...
    charming_coder阅读 1,337评论 1 8
  • 1. 概念 ThreadLocal 用于提供线程局部变量,在多线程环境可以保证各个线程里的变量独立于其它线程里的变...
    zly394阅读 1,841评论 0 1
  • 写在前面 早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决...
    AirLan阅读 2,636评论 2 5
  • 2017年7月26日 晴转阵雨 恍恍惚惚的,脑袋转动着计划,哪些事情还没做的,哪些事情做到一半的,哪些事情是要准备...
    叮铛之眼阅读 239评论 0 0
  • 《河东狮吼》中有这么一段戏,皇上说,河东刘氏,你看清楚你的老公,你看他天生的风流倜傥,才华横溢,命中注定要招风引蝶...
    铭格阅读 211评论 0 2