现在的位置: 首页 > 编程 > 正文

ThreadLocal本地线程变量的理解

2017年03月06日 编程 ⁄ 共 1741字 ⁄ 字号 暂无评论
  一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程。
     也就是说,同一线程贯通N层,不同的线程可能由于参数等不同会对程序中的某些变量进行修改,但是又要防止修改后的值对其它线程产生影响,因为不同的线程可以同时运行滴,这就需要我们解决对某些线程共享的变量的访问冲突问题。ThreadLocal本地线程变量就是一种解决方式,它通过将程序中不安全的变量封装进ThreadLocal中,这相当于为每一个线程提供一个独立的变量副本(其实是不同的对象),线程修改变量的值对其它线程来说没影响了,因为其它线程有自己的一个副本信息。
 
 
代码理解:
 1 // 借助ThreadLocal对象每个线程只创建一个实例
 2 public static final String dateFormat="yyyy-MM-dd";
 3 
 4 private static final ThreadLocal<DateFormat> dfThreadLocal=new ThreadLocal<DateFormat>(){
 5      @Override
 6      protected DateFormat initialValue() {
 7          return new SimpleDateFormat(dateFormat);
 8      }
 9 };
10 
11 public static String dateToString(Date date){
12      return dfThreadLocal.get().format(date);
13 }

 

  对于每个线程,都有一个类似于Map的东西ThreadLocalMap(ThreadLocal的静态类 ),那它里面保存了什么东东呢,肯定是key-value啊,key就是上面代码中的共享静态变量 dfThreadLocal,value就是DateFormat实例了,即new SimpleDateFormat(dateFormat)这个东东。那接下来,在线程内我要如何去获取这个值呢,就是靠dfThreadLocal.get()实现滴,方法源码如下:
 1 ThreadLocal .ThreadLocalMap inheritableThreadLocals = null ;
 2  
 3 public T get () {
 4     Thread t = Thread.currentThread ();
 5     ThreadLocalMap map = getMap(t );
 6     if ( map != null) {
 7         ThreadLocalMap.Entry e = map.getEntry (this);
 8         if ( e != null)
 9             return ( T)e .value;
10     }
11     return setInitialValue ();
12 }
13 
14 ThreadLocalMap getMap (Thread t) {
15    return t .inheritableThreadLocals;
16 }
 
   可以很明显的看出,首先根据Thread.currentThread ()获取到inheritableThreadLocals(即ThreadLocalMap,他是Thread的一个变量),然后将this(即最上面代码的dfThreadLocal对象)作为key(或索引)获取到真正的值T(就是SimpleDateFormat对象)啊,至此应该比较清楚了。
    为什么不同的线程有各自的值,因为 不同的线程--->不同的ThreadLocalMap对象(线程的变量)--->通过相同的key(如果有被static修饰)获取到不同的value值
  备注:一般都被static修饰,因为可以避免在一个线程内可能发生的重复创建TSO(Thread Specific Object,即ThreadLocal所关联的对象),被statis修饰了,同一线程key也肯定一样,value也肯定只有一份了。
 一个ThreadLocal实例关联当前线程的一个TSO对象,如果把ThreadLocal声明为实例变量,那么每创建一个类实例就会导致一个TSO实例诞生,这肯定没有这个必要滴。
 
更多文章请见我的个人博客http://www.acanblog.com
【上篇】
【下篇】

给我留言

您必须 [ 登录 ] 才能发表留言!

×