ThreadLocal源码解析,以及ThreadLocal、ThreadLocalMap、Thread 三者之间的关系
2016-01-21 14:20
519 查看
ThreadLocal、ThreadLocalMap、Thread 三者之间的关系
ThreadLocalMap 是 ThreadLocal 的内部类,Thread 中有个 ThreadLocalMap 成员变量 threadLocalsThreadLocal源码解析
下面看一下,jdk 关于 ThreadLocal apiThreadLocal类 get 方法源码
public Object get() { Thread thread = Thread.currentThread(); ThreadLocalMap threadlocalmap = getMap(thread); if(threadlocalmap != null) { ThreadLocalMap.Entry entry = threadlocalmap.getEntry(this); if(entry != null) return entry.value; } return setInitialValue(); } private Object setInitialValue() { Object obj = initialValue(); Thread thread = Thread.currentThread(); ThreadLocalMap threadlocalmap = getMap(thread); if(threadlocalmap != null) threadlocalmap.set(this, obj); else createMap(thread, obj); return obj; } protected Object initialValue() { return null; }当get一个值时,
获取当前线程,调用 getMap 方法获取当前线程的 ThreadLocalMap,如果获取的 ThreadLocalMap != null 那么就将 ThreadLocalMap 中保存的 value 返回给调用者。如果获取的 ThreadLocalMap == null 那么调用 setInitialValue 方法,setInitialValue方法中调用了 initialValue 方法,并将 initialValue 方法的返回值 obj 保存到 ThreadLocalMap 中,然后将 返回值 obj
返回给调用者。
ThreadLocal类 set 方法源码
public void set(Object obj) { Thread thread = Thread.currentThread(); ThreadLocalMap threadlocalmap = getMap(thread); if(threadlocalmap != null) threadlocalmap.set(this, obj); else createMap(thread, obj); } ThreadLocalMap getMap(Thread thread) { return thread.threadLocals; } void createMap(Thread thread, Object obj) { thread.threadLocals = new ThreadLocalMap(this, obj); }
当set一个值时,获取当前线程,调用 getMap 方法获取当前线程的 ThreadLocalMap,如果获取的 ThreadLocalMap == null 那么调用 createMap 方法创建一个ThreadLocalMap,并将 obj 放入到 ThreadLocalMap 中。(注意:ThreadLocalMap 中 key 是 ThreadLocal,value 是 传入的 obj参数。 为什么ThreadLocalMap 中 key 是 ThreadLocal,因为一个线程可以有多个 ThreadLocal
)
ThreadLocal类 remove 方法源码
public void remove() { ThreadLocalMap threadlocalmap = getMap(Thread.currentThread()); if(threadlocalmap != null) threadlocalmap.remove(this); }
删除当前 ThrealLocal 对应的 value
实例代码
public static void main(String[] args) { ThreadLocal<String> tl = new ThreadLocal<String>(); String str = tl.get(); System.out.println("输出字符串:" + str); } 输出结果 输出字符串:null public static void main(String[] args) { ThreadLocal<String> tl = new ThreadLocal<String>(){ @Override protected String initialValue() { return "lp"; } }; String str = tl.get(); System.out.println("输出字符串:" + str); } 输出结果 输出字符串:lp 至于为什么输出结果 不一样,我想打架看了上面的源码解析应该都明白了吧。 如果不想重写 ThreadLocal 中的 initialValue 方法 也可以先调用 set 方法 再 调用 get 方法,就像下面这样 public static void main(String[] args) { ThreadLocal<String> tl = new ThreadLocal<String>(); tl.set("lp"); String str = tl.get(); System.out.println("输出字符串:" + str); } 输出结果 输出字符串:lp
补充
ThreadLocal 的线程安全性稍差的堂兄弟,InheritableThreadLocal
ThreadLocal 类有一个亲戚,InheritableThreadLocal,它以相似的方式工作,但适用于种类完全不同的应用程序。创建一个线程时如果保存了所有
InheritableThreadLocal对象的值,那么这些值也将自动传递给子线程。如果一个子线程调用
InheritableThreadLocal的
get(),那么它将与它的父线程看到同一个对象。为保护线程安全性,您应该只对不可变对象(一旦创建,其状态就永远不会被改变的对象)使用
InheritableThreadLocal,因为对象被多个线程共享。
InheritableThreadLocal很合适用于把数据从父线程传到子线程,例如用户标识(user
id)或事务标识(transaction id),但不能是有状态对象,例如 JDBC
Connection。
相关文章推荐
- _weak typeof(self) weakSelf = self
- mysql 权限
- HDU 1084 What Is Your Grade? (模拟题)
- AndroidSutdio与Git@osc
- swift附属脚本
- C#数组初始化(全)
- oracle:RETURNING 子句
- python:笔记for循环中的else
- Jexus 网站服务器和 ASP.NET 跨平台开发
- 最大不能表示的数
- WSAAsyncSelect模型实例讲解
- <笔试><面试>C/C++单链表相关(4)判断两链表是否相交,求交点(链表不带环/可能带环)
- Struts2学习笔记——Struts2与Spring整合
- mysql 权限 备份
- 实现listview单选效果
- 当Java代码遇上抽象、重载加重写,一切都不美好了
- Git和Gitlab协同工作
- Error: Target id 'android--1' is not valid. Use 'android.bat list targets' to get the target ids.
- 手把手带你画一个漂亮蜂窝view Android自定义view
- 如何在SQL中先排序后分组