今天听到一个老哥说道ThreadLocal在源码设计上面的一些好处,于是决定把ThreadLocal源码彻底分析一下。

首先,我们来看下set方法

可以看到,这个方法里,先获得了当前线程,之后将当前线程传入了一个方法

此处返回了当前线程的一个成员变量

此时我们第一次调用,肯定为空,那么我们进入为空的判断看下方法

可以看到,new了一个ThreadLocalMap并将当前的ThreadLocal对象作为键,我们要存入的值作为值传入

来看下这个ThreadLocalMap到底为何物吧。

这就是它的庐山真面目,一个ThreadLocal里的内部类,我们看下它的构造方法

创建了一个16长度的Entry数组

之后做了一个二进制与运算,拿到一个整型,并将我们传入的this和值当做参数传入了一个Entry对象并赋值给了数组,请记住这里面做位运算的数是使用了AutomicInteger做++操作的,因为ThreadLocal可以被多个线程转换为索引的

这就是最后的操作,将我们的当前ThreadLocal对象变成了一个弱引用,方便回收,并将我们传入的值赋值给了其内部的变量value.

再来看下我们的get()方法

可以看到,先拿到了我们当前线程,并通过当前线程拿到了当前的ThreadLocalMap,这里不再截图,可以看上面set()方法的讲解

如果map不为空的话就会将我们的this传入getEntity方法()

可以看到,依然是做了与二进制运算拿到保存在Entry数组里对应的Entry.

再次回到此图,可以看到直接返回了我们保存在Entry中value变量的值。

而如果Map为空呢?

点进initialValue()方法

返回了一个Null.

并且因为接下来如果当前线程的ThreadLocalMap不为空则将当前ThreadLocal与null值传入。

如果为空则创建一个。

总结:ThreadLocal实现了多线程间能根据线程来保存值的原因在于它会拿到当前线程里的一个属性,ThreadLocalMap,并且因为是线程里的属性,所以当然是线程安全的。之后创建一个数组,并将创建一个将我们ThreadLocal以及我们要存入的值作为参数传入的Entry对象,并存入数组。而在Entry对象内部则是将我们的this变成了一个弱引用,并将我们的值赋值给了它内部的一个成员变量。

而当我们想要拿到的时候,它则是从当前线程拿到对应的ThreadLocalMap,并通过map将this传入拿到当前线程对应的Entry,之后直接从Entry中取到值

此处可能有点难以理解,但只要记住,我们的ThreadLocal是唯一的,但我们的ThreadLocalMap()是每个线程都不同的,它是线程的一个属性。我们存入的时候,是根据这个ThreadLocal获得索引存入table数组中的。所以我们才能通过固定的ThreadLocal再次拿到索引,从而在不同的map里拿到对应Entry,达到线程隔离的效果。

2018/3/3 解析ThreadLocal源码的更多相关文章

  1. 并发编程(四)—— ThreadLocal源码分析及内存泄露预防

    今天我们一起探讨下ThreadLocal的实现原理和源码分析.首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两 ...

  2. 并发-ThreadLocal源码分析

    ThreadLocal源码分析 参考: http://www.cnblogs.com/dolphin0520/p/3920407.html https://www.cnblogs.com/coshah ...

  3. 硬核剖析ThreadLocal源码,面试官看了直呼内行

    工作面试中经常遇到ThreadLocal,但是很多同学并不了解ThreadLocal实现原理,到底为什么会发生内存泄漏也是一知半解?今天一灯带你深入剖析ThreadLocal源码,总结ThreadLo ...

  4. Java多线程9:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

  5. Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试

    摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就 ...

  6. HtmlAgilityPack --解析Html源码

    最近项目需要从网络上抓取一下数据解析Html源码,奈何正则表达式难写,于是网上搜索找到了“ HtmlAgilityPack”类库,敏捷开发,果然效率非同寻常. 在此做笔记,写下心得,顺便给自己总结一下 ...

  7. mvc5 解析route源码实现自己的route系统

    Asp.net mvc5 解析route源码实现自己的route系统   url route 路由系统的责任是找到匹配的路由,创建路由数据,并将请求分配给一个处理程序. 选择动作是 MVC 的处理程序 ...

  8. 浩哥解析MyBatis源码(十)——Type类型模块之类型处理器

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6715063.html 1.回顾 之前的两篇分别解析了类型别名注册器和类型处理器注册器,此二 ...

  9. Java多线程学习之ThreadLocal源码分析

    0.概述 ThreadLocal,即线程本地变量,是一个以ThreadLocal对象为键.任意对象为值的存储结构.它可以将变量绑定到特定的线程上,使每个线程都拥有改变量的一个拷贝,各线程相同变量间互不 ...

随机推荐

  1. 转 ORA-00054 的解决方法

    统有一个不用的索引,想删除这个索引, SQL> drop index GPSTIME_GLOBAL_INDEX  2  /drop index GPSTIME_GLOBAL_INDEX      ...

  2. WPF学习08:MVVM 预备知识之COMMAND

    WPF内建的COMMAND是GOF 提出的23种设计模式中,命令模式的实现. 本文是WPF学习07:MVVM 预备知识之数据绑定的后续,将说明实现COMMAND的三个重点:ICommand  Comm ...

  3. 简单工厂模式及php实现

    简单工厂模式(Simple Factory Pattern): 又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式.在简单工厂模式中,可以根据参数的不同返回不同类 ...

  4. 掌握Spark机器学习库-02-mllib数据格式

    MLlib 1.MLlib介绍 1)MLlib特点 2)哪些算法 3)阅读官方文档 MLlib提供了哪些: 算法 特征工程 管道 持久化 2.MLlib数据格式 1)本地向量 2)标签数据 3)本地矩 ...

  5. 使用Jenkins进行android项目的自动构建(1)

    环境搭建 1. 下载JDK,安装,并将JDK的安装目录加入到环境变量JAVA_HOME,将JDK的bin目录加入到环境变量PATH. 2. 下载Android SDK,解压,并将SDK的安装目录加入到 ...

  6. 在 Windows Server 上搭建 *** 服务端(转载加亲测)

    转载自:https://diveng.io/build-shadowsocks-server-on-windows-server.html 下面的教程建议大家使用第一种方法安装,说是比较简单.我则使用 ...

  7. myslq 5.7 root 默认密码

    sudo sumysqld_safe --skip-grant-tables --skip-networking & UPDATE mysql.user SET password=PASSWO ...

  8. 我用的主机,推荐给大家【gegehost】【戈戈主机】

    炎炎夏日冰点价格:戈戈主机史上最大优惠促销活动 1.7月1日至8日:买主机优惠大促销:主机买一送一,不限购买数量 请您通过客户中心或者淘宝购买一个主机之后,登录客户中心,提交问题, 提供要赠送的主机的 ...

  9. PHP自定义函数及内部函数考察点

    变量的作用域和静态变量 变量的作用域 变量的作用域也称变量的范围,变量的范围即它定义的上下文背景(也是它的生效范围).大部分的PHP变量只有一个单独的范围.这个单独的范围跨度同样包含了include和 ...

  10. JAVA编程不得不看的几本经典书籍

    为了帮助对java编程感兴趣的同学更好.更快的提高编程技术,武汉北大青鸟光谷校区专业老师在此推荐几本学习编程非常有用的书籍,以供大家参考. 入门类 1.<java从入门到精通>(第3版) ...