首页 > 学院 > 开发设计 > 正文

ThreadLocal本地线程变量的理解

2019-11-06 06:22:18
字体:
来源:转载
供稿:网友
        一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程。        也就是说,同一线程贯通N层,不同的线程可能由于参数等不同会对程序中的某些变量进行修改,但是又要防止修改后的值对其它线程产生影响,因为不同的线程可以同时运行滴,这就需要我们解决对某些线程共享的变量的访问冲突问题。ThreadLocal本地线程变量就是一种解决方式,它通过将程序中不安全的变量封装进ThreadLocal中,这相当于为每一个线程提供一个独立的变量副本(其实是不同的对象),线程修改变量的值对其它线程来说没影响了,因为其它线程有自己的一个副本信息。

代码理解:

// 借助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);}

        对于每个线程,都有一个类似于Map的东西ThreadLocalMap(ThreadLocal的静态类 ),那它里面保存了什么东东呢,肯定是key-value啊,key就是上面代码中的共享静态变量 dfThreadLocal,value就是DateFormat实例了,即new SimpleDateFormat(dateFormat)这个东东。那接下来,在线程内我要如何去获取这个值呢,就是靠dfThreadLocal.get()实现滴,方法源码如下:    
ThreadLocal .ThreadLocalMap inheritableThreadLocals = null ;public T get () {	Thread t = Thread.currentThread ();	ThreadLocalMap map = getMap(t );// 获取到inheritableThreadLocals	if ( map != null) {		ThreadLocalMap.Entry e = map.getEntry (this);// this作为key,this就是本地线程变量,获取Entry		if ( e != null)			return ( T)e .value;	}	return setInitialValue ();}ThreadLocalMap getMap (Thread t) {   return t .inheritableThreadLocals;}        可以很明显的看出,首先根据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
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表