【惊天真相】ThreadLocal原理与源码分析-精品文档资料整理.docx
-
资源ID:73267944
资源大小:15.50KB
全文页数:5页
- 资源格式: DOCX
下载积分:14.8金币
快捷下载

会员登录下载
微信登录下载
三方登录下载:
微信扫一扫登录
友情提示
2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
|
【惊天真相】ThreadLocal原理与源码分析-精品文档资料整理.docx
【惊天真相】ThreadLocal原理与源码分析 没有这篇我真的弄不懂 这篇观点正确 诲人不倦 一定是位技术深沉的前辈 好 闲言少叙 讲正题。 先是一个使用ThreadLocal的例子 private static final ThreadLocal Integer CONTEXT new ThreadLocal ();public void setVal(int i) CONTEXT.set(i);public int getVal() Integer val CONTEXT.get(); return val null ? 0 : val; 这是一个没什么用的例子 只为讲明问题。setVal方法可以往如今这个线程的“线程本地空间 先不用管这个名词啥意思 就当是线程间互不相关的各自的一块空间 里存进去一个Integer或更新已有Integer的值 getVal方法是获取这个值。threadlocal的作用就在于可以让每个线程各有各的值 互不影响 线程平安 那么从源码角度分析threadlocal是怎么做到的。 首先是看一下ThreadLocal.set(T value)这个方法 /* * Sets the current thread s copy of this thread-local variable * to the specified value. Most subclasses will have no need to * override this method, relying solely on the link #initialValue * method to set the values of thread-locals. * param value the value to be stored in the current thread s copy of * this thread-local. public void set(T value) Thread t Thread.currentThread(); ThreadLocalMap map getMap(t); if (map ! null) map.set(this, value); else createMap(t, value); 来一行行看ThreadLocal在这里干了什么 先是获取当前线程 然后调用了getMap 传入当前线程作为参数 获得到了一个类型为ThreadLocalMap的对象。好 如今解决两个问题 注意接下来提到的类名 1、ThreadLocalMap是啥 跳过去看一下发现 ThreadLocalMap是ThreadLocal的一个内部类 ThreadLocalMap内部有一段这样的代码 static class Entry extends WeakReference ThreadLocal /* The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) super(k); value 看到这里可能很惊奇 “纳尼 键的类型是ThreadLocal 暂且搁置这个疑问 Entry的值是Object 嗯 看来每个线程里的“数据副本就是存在这。 2、getMap干了啥 跳过去看一下 是这样的 /* * Get the map associated with a ThreadLocal. Overridden in * InheritableThreadLocal. * param t the current thread * return the map ThreadLocalMap getMap(Thread t) return t.threadLocals; 传进去的是当前线程 返回来的是当前线程对象里的一个成员变量 而且类型是ThreadLocalMap “纳尼 Thread类里有这个成员变量 没错 Thread类里持有一个ThreadLocalMap对象 不信跳过去看 Thread类里有这句话 /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals null; 这是Thread类的一个成员变量。返回去的就是这个 每个Thread都自己有一个的 存在于该Thread栈空间的 以及该Thread中声明的部分变量没什么区别的 从存储的角度上讲 一个Entry为 ThreadLocal, Object 的ThreadLocalMap。 回头看之前的ThreadLocal.set(T value) 再贴一遍代码 public void set(T value) Thread t Thread.currentThread(); ThreadLocalMap map getMap(t); if (map ! null) map.set(this, value); else createMap(t, value); 获取到了当前线程的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这个名字 觉得像冷笑话一样 “线程本地 意思是讲“线程自己拿自己的本地空间 线程里的部分变量 存数据。