一般的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 );
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;
}
 
   可以很明显的看出,首先根据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本地线程变量的理解的更多相关文章

  1. Java 类 ThreadLocal 本地线程变量

    前言:工作中将要使用ThreadLocal,先学习总结一波.有不对的地方欢迎评论指出. 定义 ThreadLocal并不是一个Thread,而是Thread的局部变量.这些变量不同于它们的普通对应物, ...

  2. Java Concurrency - ThreadLocal, 本地线程变量

    共享数据是多线程应用最常见的问题之一,但有时我们需要为每个线程保存一份独立的变量.Java API 提供了 ThreadLocal 来解决这个问题. 一个 ThreadLocal 作用的例子: imp ...

  3. ThreadLocal = 本地线程?

    一.定义 ThreadLocal是JDK包提供的,从名字来看,ThreadLocal意思就是本地线程的意思. 1.1 是什么? 要想知道他是个啥,我们看看ThreadLocal的源码(基于JDK 1. ...

  4. Flask中的ThreadLocal本地线程,上下文管理

    先说一下和flask没有关系的: 我们都知道线程是由进程创建出来的,CPU实际执行的也是线程,那么线程其实是没有自己独有的内存空间的,所有的线程共享进程的资源和空间,共享就会有冲突,对于多线程对同一块 ...

  5. Java线程变量问题-ThreadLocal

    关于Java线程问题,在博客上看到一篇文章挺好的: https://blog.csdn.net/w172087242/article/details/83375022#23_ThreadLocal_1 ...

  6. 本地线程-ThreadLocal

    线程本地存储是一个自动化机制,可以为使用相同变量的每个不同的线程都创建不同的存储.简单来说,就是对于某个变量,针对不同的线程存储不同的值. 实例: import java.util.Random; i ...

  7. 线程变量ThreadLocal的使用

    我们有时候会通过token进行多次查询(猪:token是redis中的key),比如: 一次是在登录拦截器中,一次是在controller的业务中查询,这样存在性能和资源的浪费问题!!! 那么如何将拦 ...

  8. Java代码质量改进之:使用ThreadLocal维护线程内部变量

    在上文中,<Java代码质量改进之:同步对象的选择>,我们提出了一个场景:火车站有3个售票窗口,同时在售一趟列车的100个座位.我们通过锁定一个靠谱的同步对象,完成了上面的功能. 现在,让 ...

  9. 【java】ThreadLocal线程变量的实现原理和使用场景

    一.ThreadLocal线程变量的实现原理 1.ThreadLocal核心方法有这个几个 get().set(value).remove() 2.实现原理 ThreadLocal在每个线程都会创建一 ...

随机推荐

  1. iOS获取本地时间

    NSDate *currentDate = [NSDate date];//获取当前时间,日期 NSDateFormatter *dateFormatter = [[NSDateFormatter a ...

  2. uml系列(六)——行为图:活动&状态

    说完uml的静态图了,说一下uml的动态的表示吧. uml的行为图,uml的行为图主要用来设计程序的行为.还是老规矩,先来张图: 行为图包含活动图和状态图两种. 先来说下活动图:活动图是由活动的节点和 ...

  3. 【Java基础】线程和并发机制

    前言 在Java中,线程是一个很关键的名词,也是很高频使用的一种资源.那么它的概念是什么呢,是如何定义的,用法又有哪些呢?为何说Android里只有一个主线程呢,什么是工作线程呢.线程又存在并发,并发 ...

  4. js加载XML文件

    // XML文件 <?xml version="1.0" encoding="gb2312"?> <root> <father n ...

  5. plugman创建cordova插件

    一.安装plumam npm install -g plugman 二.安装完之后,就可以创建plugin plugman create --name --plugin_id --plugin_ver ...

  6. 20130620—ant和java杂学随笔

    ant知识点: 1.使用属性定义相对路径的时候,一定要使用location,而不要去使用value  对于<property></property>中location和valu ...

  7. could not resolve host: github.com 问题解决办法

    向github提交代码时出现问题,如图: 代码push失败,提示could not resolve host: github.com     解决办法:   1.打开终端,输入:ping github ...

  8. Linux配置JDK

    在etc/profile文件下添加 export JAVA_HOME=/root/Desktop/jdk1.7.0_79 export CLASSPATH=/root/Desktop/jdk1.7.0 ...

  9. Kettle 5.0源码编译

    下载源码请参考上一篇博文Kettle4.4.2源码分析 Kettle 5.0以前的库文件通过ant管理,5.0+的库文件通过ant+ivy管理.Eclipse一般都是安装ant插件,不安装ivy插件, ...

  10. JS中的作用域链

    在js中数据的声明方式有两种: 1.用var声明,例如:var num = 10: 2.直接声明,例如:num = 10: 两种声明方式在某些情况下是有区别的: var data = 10; func ...