一般的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. Java中正则表达式去除html标签

    Java中正则表达式去除html的标签,主要目的更精确的显示内容,比如前一段时间在做类似于博客中发布文章功能,当编辑器中输入内容后会将样式标签也传入后台并且保存数据库,但是在显示摘要的时候,比如显示正 ...

  2. Swift 2.0 自定义cell和不同风格的cell

    昨天我们写了使用系统的cell怎样创建tableView,今天我们再细分一下,就是不同风格的cell,我们怎写代码.先自己创建一个cell,继承于UItableviewcell 我们看看 cell 里 ...

  3. JVM内存

    大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) ,   VM Stack( ...

  4. GAME(A)性能测试过程模型

  5. Dockerfile注意事项

    准则 尽量将Dockerfile放在空目录中,如果目录中必须有其他文件,则使用.dockerignore文件. 避免安装不必须的包. 每个容器应该只关注一个功能点. 最小化镜像的层数. 多行参数时应该 ...

  6. linux文件和目录权限

    linux系统文件和目录的权限说明 文件权限是Linux系统的第一道安全防线,基本的权限有读取(r).写入(w)和执行(x): 文件访问模式 读取:用户能够读取文件信息,查看文件内容. 写入:用户可以 ...

  7. Kafka 0.10.1.1 特点

    1.Consumer优化:心跳线程可作为后台线程,提交offset,剥离出poll函数 问题:0.10新设计的consumer是单线程的,提交offset是在poll中.本次的poll调用,提交上次p ...

  8. 新手学js的效果图1---( 淘宝等商城货物查看特效)

    本人结合之前所学一起写了,多个特效,只是新手自己瞎鼓捣的,思路清晰,具体实现的货物放大镜等,替换当中的img地址就可以查看特效 <!DOCTYPE html> <html lang= ...

  9. 关于rem的使用和less编译工具考拉

    前提: 1.使用rem的前提是首先要设置好页面的根节点的大小: <script> (function(){ var html = document.documentElement; var ...

  10. http服务搭建

    http服务器搭建 主配置文件在 /etc/httpd/conf/httpd.conf 安装http  yum install httpd -y 启动http服务器  systemctl start ...