今天听到一个老哥说道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. B. Hongcow Solves A Puzzle

    http://codeforces.com/contest/745/problem/B 题目要求的是,给定一个图形,要求里面判断是否有矩形,且仅有一个 就是 XXX.... XXX...X 是不行的, ...

  2. sdut1283Five in a Row, Again

    一简单的状压题 比赛时跑偏了 ,脑子最近乱的跟浆糊似得呢.. #include <iostream> #include<cstdio> #include<cstring& ...

  3. 窗体WINFORM

    窗体的事件:删除事件:先将事件页面里面的挂好的事件删除,再删后台代码里面的事件 Panel是一个容器 1.Label -- 文本显示工具Text:显示的文字取值.赋值:lable1.Text 2.Te ...

  4. BOW-js浏览器对象模型

  5. 升级 Cocoapods 到1.2.0指定版本,降低版本及卸载

    =====================升级版本=================== CocoaPods 1.1.0+ is required to build SnapKit 3.0.0+. 在 ...

  6. 51全志R58平台Android4.4下Camera的HAL层修改

    51全志R58平台Android4.4下Camera的HAL层修改 2018/11/7 15:20 版本:V1.0 开发板:SC5806 1.系统编译: (略) 2.全志R58平台Android4.4 ...

  7. 详解java中staitc关键字

    一.static定义 static是静态修饰符意思,什么叫静态修饰符呢?大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到 ...

  8. Farseer.net轻量级ORM开源框架 V1.x 入门篇:存储过程实体类映射

    导航 目   录:Farseer.net轻量级ORM开源框架 目录 上一篇:Farseer.net轻量级ORM开源框架 V1.x 入门篇:视图的数据操作 下一篇:Farseer.net轻量级ORM开源 ...

  9. 让TortoiseGit记住帐号密码方法

    我的电脑环境是: Windows7 64x   系统用户名是:steden 所以,我的路径是:C:\Users\steden\ 具体要根据你的系统环境及当前用户名来决定. 在这里,有个文件:.gitc ...

  10. 迅为iTOP-4418嵌入式开发板初体验

    iTOP-4418开发板预装 Android4.4.4 系统, 支持9.7 寸.7 寸.4.3 寸屏幕. 参数:核心板参数 尺寸 50mm*60mm高度 核心板连接器为1.5mmCPU ARM Cor ...