官方对ThreadLocal的描述:

  "该类提供了线程局部(thread-local)变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其get或set方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal实例通常是类中的private static字段,它们希望将状态与某一个线程(例如,用户ID或事物ID)相关联。"

《Thinking in Java》中的描述:

  防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享。线程本地存储是一种自动化机制,可以为使用变量的每个不同的线程都创建不同的存储。因此,如果你有5个线程都要使用变量x所表示的对象,那线程本地存储就会生成5个用于x的不同的存储块。主要是,它们使得你可以将状态与线程关联起来。

三个要点:

  1.每个线程都有自己的局部变量

    每个线程都有一个独立于其它线程的上下文来保存这个变量,一个线程的本地变量对其它线程是不可见的。

  2.独立于变量的初始化副本

    ThreadLocal可以给一个初始值,而每个线程都会获得这个初始化值的一个副本,这样才能保证不同的线程都有一份拷贝。

  3.状态与某一个线程相关联

    ThreadLocal不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制,就像《Thinking in Java》中描述的那样:”它们使得你可以将状态与线程关联起来。“理解这点对正确使用ThreadLocal至关重要。

源码举例:

  从输出的结果可以看出,五个线程处理自己的本地变量值。

  而这个测试的结果,并没有相同。这是因为实例为对象,所以初始值为一个对象的引用,那么五个线程的副本就是这个对象的引用的副本,也就是说这些引用还是指向同一个对象,所以就出现了这种情况。

ThreadLocal的接口方法:

  • void set(T value):设置当前线程的线程局部变量的值;
 1 public void set(T value) {
 2    Thread t = Thread.currentThread();
 3    ThreadLocalMap map = getMap(t);
 4
 5    if (map != null)
 6      map.set(this, value);
 7   //说明线程第一次使用线程本地变量(注意这里的第一次含义)
 8    else
 9        createMap(t, value);
10 }

  • public T get():该方法返回当前线程所对应的线程局部变量;
 1 public T get() {
 2   //获取当前执行线程
 3   Thread t = Thread.currentThread();
 4   //取得当前线程的ThreadLocalMap实例
 5   ThreadLocalMap map = getMap(t);
 6   //如果map不为空,说明该线程已经有了一个ThreadLocalMap实例
 7   if (map != null) {
 8     //map中保存线程的所有的线程本地变量,我们要去查找当前线程本地变量
 9     ThreadLocalMap.Entry e = map.getEntry(this);
10     //如果当前线程本地变量存在这个map中,则返回其对应的值
11     if (e != null)
12          return (T)e.value;
13   }
14    //如果map不存在或者map中不存在当前线程本地变量,返回初始值
15    return setInitialValue();
16 }

  • public void remove():将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。当线程结束后,对应该线程的局部变量将被自动垃圾回收,所以显示调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度;
  • protected T initialValue():返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的,这个方法是一个延迟调用方法,在线程第1次调用get()或set(T)时才执行,并且仅执行1次。ThreadLocal中的默认实现直接返回一个null。

这里注意,ThreadLocal中是有一个Map,但这个Map不是我们平时使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一个内部类,不对外使用的。当使用ThreadLocal存值时,首先是获取到当前线程对象,然后获取到当前线程本地变量Map,最后将当前使用的ThreadLocal和传入的值放到Map中,也就是说ThreadLocalMap中存的值是[ThreadLocal对象, 存放的值]这样做的好处是,每个线程都对应一个本地变量的Map,所以一个线程可以存在多个线程本地变量。下面提供一个简单的实现版本:

Java中ThreadLocal的深入理解相关推荐

  1. java中ThreadLocal的使用

    文章目录 在Map中存储用户数据 在ThreadLocal中存储用户数据 java中ThreadLocal的使用 ThreadLocal主要用来为当前线程存储数据,这个数据只有当前线程可以访问. 在定 ...

  2. Java中Map集合如何理解(四)——精简

    目录 引言 概念 Map集合实现类 HashMap LinkedHashMap TreeMap 默认排序 自定义排序方式 常用API 遍历Map集合 键找值 键值对 Lambda表达式 结束语 引言 ...

  3. java中class对象的理解 讲得相当不错 很接地气 引用下

    https://blog.csdn.net/mcryeasy/article/details/52344729 https://blog.csdn.net/dufufd/article/details ...

  4. Java中 synchronized 关键字的理解

    synchronized 关键字的理解 在Java中,synchronized 是一个重量级的控制并发的关键字. 这个关键字可以保证并发过程所必须的"原子性","可见性& ...

  5. java中static关键字的理解(转载)

    static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列 ...

  6. JAVA 中转义符的理解

    生物信息中有时候会遇到JAVA写的程序,今天阅读源码的时候发现对于正则中的转义符不好理解,后来查资料后终于弄明白了,这里详细说明一下: 字符串的表示有三种方法:1.直接单字符,例如"A&qu ...

  7. java中对于框架的理解_接触Java项目一周后对一些基本框架的理解 | 学步园

    最近一周接触了一个Java EE的B/S项目,里面用到了SSH,部分持久层用的是ibatis,接触完后觉得有收获,于是把认识到的记录下来.同时欢迎高手拍砖. 现在终于知道所谓的三层框架(视图层,业务逻 ...

  8. 详细了解java中的null_深入理解java中的null“类型”

    本文研究的主要是java中的null"类型"的相关实例,具体介绍如下. 先给出一道简单的null相关的题目,引发我们对null的探讨,后面会根据官方语言手册对null"类 ...

  9. Java中关于多态的理解

    Java中多态的理解 JAVA中的多态可以简单的理解为一种事物的多种形态,当然多态是在继承的基础上有重写才存在.(因为这篇文章是转载过来的,大部分地方持支持的态度,但也有一些地方存在个人态度,比如这里 ...

最新文章

  1. 菜鸟学python 哪吒_Python 学习之路 (前言)
  2. 【网络安全】xhCMS代码审计思路
  3. windows安装两个版本JDK
  4. Python爬虫西安七天天气预报
  5. java JUC线程池:Executors.newSingleThreadExecutor代码示例
  6. CCTMXTiledMap的使用
  7. 光纤中继器的安装调试
  8. 个基于TensorFlow的简单故事生成案例:带你了解LSTM
  9. go 模板(template)的常用基本语法
  10. [转载] python的短逻辑
  11. 宝贝,后端接口如何提高性能?
  12. 上海蓝光集团信息安全建设方案
  13. 卫星轨道的计算是利用计算机的,轨道计算
  14. C语言例题:温度转换
  15. Android获取WIFI 的ssid 方法适配Android9.0
  16. PBR基本原理和概念以及PBR流程
  17. 快手火山抖音视频(包含其他视频)跨平台操作搬运,下载,消重,全自动操作解放双手...
  18. 致敬每一位劳动者,感恩每一次付出!清微智能祝您劳动节快乐~
  19. Node.js—Express、Express 路由 、Express 中间件、使用 Express 写接口
  20. python的第三方库汇总

热门文章

  1. 【Data guard】Failover切换
  2. Linux之route命令
  3. 在线JSON转io-ts工具
  4. es管理kabina_ES和Kibana在Linux上的安装
  5. 【vue】vue +element 搭建项目,要求既支持pc端又支持移动端
  6. springloaded热加载
  7. Golang Import使用入门
  8. 2016年度太和顾问北京高科技行业人力资本数据信息发布
  9. 使用surface初体验
  10. .NET与COM互操作系列