ThreadLocal本地线程变量的理解
2017-04-17 15:29
573 查看
转自:http://www.cnblogs.com/acanblog/p/6507674.html
一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程。
也就是说,同一线程贯通N层,不同的线程可能由于参数等不同会对程序中的某些变量进行修改,但是又要防止修改后的值对其它线程产生影响,因为不同的线程可以同时运行滴,这就需要我们解决对某些线程共享的变量的访问冲突问题。ThreadLocal本地线程变量就是一种解决方式,它通过将程序中不安全的变量封装进ThreadLocal中,这相当于为每一个线程提供一个独立的变量副本(其实是不同的对象),线程修改变量的值对其它线程来说没影响了,因为其它线程有自己的一个副本信息。
![](http://images2015.cnblogs.com/blog/1099976/201703/1099976-20170306014008156-233635070.jpg)
代码理解:
[align=left] 对于每个线程,都有一个类似于Map的东西ThreadLocalMap(ThreadLocal的静态类 ),那它里面保存了什么东东呢,肯定是key-value啊,key就是上面代码中的共享静态变量 dfThreadLocal,value就是DateFormat实例了,即new SimpleDateFormat(dateFormat)这个东东。那接下来,在线程内我要如何去获取这个值呢,就是靠dfThreadLocal.get()实现滴,方法源码如下:[/align]
[align=left] 可以很明显的看出,首先根据Thread.currentThread ()获取到inheritableThreadLocals(即ThreadLocalMap,他是Thread的一个变量),然后将this(即最上面代码的dfThreadLocal对象)作为key(或索引)获取到真正的值T(就是SimpleDateFormat对象)啊,至此应该比较清楚了。[/align]
[align=left] 为什么不同的线程有各自的值,因为 不同的线程—>不同的ThreadLocalMap对象(线程的变量)—>通过相同的key(如果有被static修饰)获取到不同的value值。[/align]
[align=left] 备注:一般都被static修饰,因为可以避免在一个线程内可能发生的重复创建TSO(Thread Specific Object,即ThreadLocal所关联的对象),被statis修饰了,同一线程key也肯定一样,value也肯定只有一份了。[/align]
[align=left] 一个ThreadLocal实例关联当前线程的一个TSO对象,如果把ThreadLocal声明为实例变量,那么每创建一个类实例就会导致一个TSO实例诞生,这肯定没有这个必要滴。[/align]
[align=left] [/align]
一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程。
也就是说,同一线程贯通N层,不同的线程可能由于参数等不同会对程序中的某些变量进行修改,但是又要防止修改后的值对其它线程产生影响,因为不同的线程可以同时运行滴,这就需要我们解决对某些线程共享的变量的访问冲突问题。ThreadLocal本地线程变量就是一种解决方式,它通过将程序中不安全的变量封装进ThreadLocal中,这相当于为每一个线程提供一个独立的变量副本(其实是不同的对象),线程修改变量的值对其它线程来说没影响了,因为其它线程有自己的一个副本信息。
![](http://images2015.cnblogs.com/blog/1099976/201703/1099976-20170306014008156-233635070.jpg)
代码理解:
// 借助ThreadLocal对象每个线程只创建一个实例 public static final String dateFormat="yyyy-MM-dd"; private static final ThreadLocal<DateFormat> dfThreadLocal=new ThreadLocal<DateFormat>(){ @Override protected DateFormat initialValue() { return new SimpleDateFormat(dateFormat); } }; public static String dateToString(Date date){ return dfThreadLocal.get().format(date); }
[align=left] 对于每个线程,都有一个类似于Map的东西ThreadLocalMap(ThreadLocal的静态类 ),那它里面保存了什么东东呢,肯定是key-value啊,key就是上面代码中的共享静态变量 dfThreadLocal,value就是DateFormat实例了,即new SimpleDateFormat(dateFormat)这个东东。那接下来,在线程内我要如何去获取这个值呢,就是靠dfThreadLocal.get()实现滴,方法源码如下:[/align]
ThreadLocal .ThreadLocalMap inheritableThreadLocals = null ; public T 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; } return setInitialValue (); } ThreadLocalMap getMap (Thread t) { return t .inheritableThreadLocals; }
[align=left] 可以很明显的看出,首先根据Thread.currentThread ()获取到inheritableThreadLocals(即ThreadLocalMap,他是Thread的一个变量),然后将this(即最上面代码的dfThreadLocal对象)作为key(或索引)获取到真正的值T(就是SimpleDateFormat对象)啊,至此应该比较清楚了。[/align]
[align=left] 为什么不同的线程有各自的值,因为 不同的线程—>不同的ThreadLocalMap对象(线程的变量)—>通过相同的key(如果有被static修饰)获取到不同的value值。[/align]
[align=left] 备注:一般都被static修饰,因为可以避免在一个线程内可能发生的重复创建TSO(Thread Specific Object,即ThreadLocal所关联的对象),被statis修饰了,同一线程key也肯定一样,value也肯定只有一份了。[/align]
[align=left] 一个ThreadLocal实例关联当前线程的一个TSO对象,如果把ThreadLocal声明为实例变量,那么每创建一个类实例就会导致一个TSO实例诞生,这肯定没有这个必要滴。[/align]
[align=left] [/align]
相关文章推荐
- 深入理解线程本地变量ThreadLocal
- 深入理解线程本地变量ThreadLocal
- 线程本地变量ThreadLocal源码解读
- 【Android应用源码分析】Java多线程:线程本地变量ThreadLocal源码分析
- Java线程(篇外篇):线程本地变量ThreadLocal
- Java并发(六):线程本地变量ThreadLocal、再聊线程池
- 线程本地变量ThreadLocal
- ThreadLocal---线程本地变量
- Java线程(篇外篇):线程本地变量ThreadLocal
- Java线程(十二)----线程本地变量ThreadLocal
- ThreadLocal,线程本地变量
- java 线程(八)线程本地变量ThreadLocal
- Java线程(篇外篇):线程本地变量ThreadLocal
- 线程本地变量ThreadLocal (耗时工具)
- Java线程(篇外篇):线程本地变量ThreadLocal
- ThreadLocal---线程本地变量
- Java线程(篇外篇):线程本地变量ThreadLocal
- Java线程外篇:线程本地变量ThreadLocal
- Java线程(篇外篇):线程本地变量ThreadLocal
- Java线程(篇外篇):线程本地变量ThreadLocal