欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ThreadLocal本地线程变量的理解

程序员文章站 2022-07-12 22:08:22
...

       一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程

       也就是说,同一线程贯通N层,不同的线程可能由于参数等不同会对程序中的某些变量进行修改,但是又要防止修改后的值对其它线程产生影响,因为不同的线程可以同时运行滴,这就需要我们解决对某些线程共享的变量的访问冲突问题。ThreadLocal本地线程变量就是一种解决方式,它通过将程序中不安全的变量封装进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 ();
        // 获取到inheritableThreadLocals
	ThreadLocalMap map = getMap(t );
	if ( map != null) {
                // this作为key,this就是本地线程变量,获取Entry
		ThreadLocalMap.Entry e = map.getEntry (this);
		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

 

  • ThreadLocal本地线程变量的理解
            
    
    博客分类: 多线程 多线程线程安全
  • 大小: 19.4 KB