ThreadLocal原理与源码分析
来源:互联网 发布:我的淘宝怎么注册账号 编辑:程序博客网 时间:2024/05/15 10:31
ThreadLocal,神神秘秘的一个东西,长久以来似乎都觉得“这玩意好屌!竟然能这么轻松地解决线程间资源冲突问题!”。然而分析下它的源码就会发现,这东西只是唬人的,原理其实就是“在各线程的堆空间里维护各线程自己的资源”,更通俗的说法就是“废话!你让每个线程在自己线程里面用自己的局部变量,发生冲突才怪!”。所以说啊这个东西就是个纸老虎,下面从头分析。
分析前感谢这篇博客:http://www.cnblogs.com/dolphin0520/p/3920407.html,没有这篇我真的弄不懂,这篇观点正确,诲人不倦,一定是位技术深厚的前辈!
好,闲言少叙,讲正题。
先是一个使用ThreadLocal的例子:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
这是一个没什么用的例子,只为说明问题。setVal方法可以往现在这个线程的“线程本地空间”(先不用管这个名词啥意思,就当是线程间互不相关的各自的一块空间)里存进去一个Integer或者更新已有Integer的值;getVal方法是获取这个值。threadlocal的作用就在于可以让每个线程各有各的值,互不影响,线程安全!
那么从源码角度分析threadlocal是怎么做到的。
首先是看一下ThreadLocal.set(T value)这个方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
来一行行看ThreadLocal在这里干了什么,先是获取当前线程,然后调用了getMap,传入当前线程作为参数,获得到了一个类型为ThreadLocalMap的对象。好,现在解决两个问题(注意接下来提到的类名):
1、ThreadLocalMap是啥?
跳过去看一下发现,ThreadLocalMap是ThreadLocal的一个内部类,ThreadLocalMap内部有一段这样的代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
看到这里可能很惊奇,“纳尼?键的类型是ThreadLocal?”,暂且搁置这个疑问,Entry的值是Object,嗯,看来每个线程里的“数据副本”就是存在这。
2、getMap干了啥?
跳过去看一下,是这样的:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
传进去的是当前线程,返回来的是当前线程对象里的一个成员变量!而且类型是ThreadLocalMap!“纳尼?!Thread类里有这个成员变量?”没错,Thread类里持有一个ThreadLocalMap对象!不信跳过去看,Thread类里有这句话:
- 1
- 2
- 3
- 1
- 2
- 3
这是Thread类的一个成员变量。返回去的就是这个,每个Thread都自己有一个的,存在于该Thread栈空间的,和该Thread中声明的局部变量没什么区别的(从存储的角度上讲),一个Entry为<ThreadLocal, Object>的ThreadLocalMap。
回头看之前的ThreadLocal.set(T value),再贴一遍代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
获取到了当前线程的ThreadLocalMap之后,我们的ThreadLocal判断了一下map是否为空,不空就存入或替换为(this, value);空就执行一个初始化的操作。set或者初始化的细节本文不赘述了。
值得注意的是,之前我们很疑惑的“键为什么是ThreadLocal”这个谜题解开了,这里不是就传入了this这个ThreadLocal嘛,这是因为一个Thread可能对应不止一个ThreadLocal,想要知道具体是Thread对应的哪个ThreadLocal,就要在Thread中维护一个ThreadLocalMap,以ThreadLocal为键,就可以找到Thread在某个ThreadLocal里对应的本地数据(本地数据指的就是Entry值的那个Object,例子里的Integer,实际上以thread内部变量的形式存在于thread对象中),这就是“Thread里为啥有个ThreadLocalMap?ThreadLocalMap为啥是个Map?键的类型为啥是ThreadLocal?”这三个问题的答案!
上面一段话比较拗口,本人水平所限,只能说成这样了,真正理解上面的话也就理解了ThreadLocal。这时候你一定会拍着大腿说,我靠!这是个什么玩意儿?原来这么简单啊!
没错,ThreadLocal的根本原理在于把数据存在了线程的各自的ThreadLocalMap中,也就是存在了线程的一个成员变量里,线程自己的内部变量当然跟别的线程互不影响,当然解决了这个问题。也就是说上面的例子里,你完全可以自己给你的线程类里加一个Integer型的成员,再写个get、set方法,就能达到完全相同的效果,这不就是所谓的“给每个线程一份数据副本”吗?只不过Java为你提供了一个名为ThreadLocal的API让你可以方便的处理这件事,比如你需要在方法间跳来跳去的时候,或者数据类型没有Integter这么简单的话。ThreadLocal不过是个方便你管理线程里数据的一个JDK提供的API而已,没什么神奇的。
回头看ThreadLocal这个名字,觉得像冷笑话一样,“线程本地”,意思是说“线程自己拿自己的本地空间(线程里的局部变量)存数据”。
- ThreadLocal原理与源码分析
- 【惊天真相】ThreadLocal原理与源码分析
- Java ThreadLocal原理与源码
- ThreadLocal与WeakReference 源码分析
- ThreadLocal的用法与源码分析
- ThreadLocal类详解与源码分析
- Threadlocal 源码分析与内存泄漏
- ThreadLocal源码分析与使用场景
- java.lang.ThreadLocal实现原理和源码分析
- ThreadLocal原理分析
- ThreadLocal原理分析
- ThreadLocal原理分析
- ThreadLocal源码分析
- Threadlocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析解密
- Byobu快捷键汇总
- (chrome)Adobe Flash 无法正常使用
- linux命令 - ln - 创建和删除软、硬链接
- 谷歌Google被墙打不开,找不到技术性资料怎么办?
- TurtleWorld
- ThreadLocal原理与源码分析
- android包体积减少利器,so动态加载
- paramiko遇到的问题
- Unity-Networking
- 处理freeMark值为空的情况
- 揭秘:成功产品经理的背后是什么?
- MAVEN Spring MVC Java Config
- hdu 2612 Find a way【BFS】
- 计数排序