ThreadLocal源码分析
2016-03-29 21:20
447 查看
ThreadLocal的作用
Java对象是线程间共享的,但有时我们需要一些线程间隔离的对象,该对象只能由同一个线程读写,对其他线程不可见。ThreadLocal正式提供了这样的机制,详细使用方式请参考Java ThreadLocal。ThreadLocal实现原理
自定义实现
在没有看源码前,如果我自己实现一个ThreadLocal,可能是这样的public class ThreadLocal<T> { private Map<Thread, T> values = new WeakHashMap<Thread, T>(); public synchronized void set(T value) { values.put(Thread.currentThread(), value); } public synchronized T get() { values.get(Thread.currentThread()); } }
JDK实现
Java源码中ThreadLocal的核心代码如下:public class ThreadLocal<T> { public T get() { Thread t = Thread.currentThread(); //从当前的Thread对象中取出ThreadLocalMap成员,key是ThreadLocal,value是set的值。 ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); } public void set(T value) { Thread t = Thread.currentThread(); //从当前的Thread对象中取出ThreadLocalMap成员,key是ThreadLocal,value是set的值。 ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; } } //threadLocals变量存放在Thread对象中 public class Thread{ /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null; /* * InheritableThreadLocal values pertaining to this thread. This map is * maintained by the InheritableThreadLocal class. */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; ... }
不同于自定义实现,源码中ThreadLocal.set(T value)的值是由Thread对象来缓存的。那么问题就来了?
1. 为什么ThreadLocal.set(T value)的值由Thread对象来缓存,为什么不像自定义实现那样放在ThreadLocal中?
我理解主要是性能考虑。如果放在ThreadLocal中,由于多线程操作同一个Map对象,将不得不加锁保护。而将value直接放在Thread对象中,不同的线程有各自的Thread对象,因此也就无需加锁。因此将value放在Thread对象中性能会好一些。大家如果有不同的见解,请指教^_^2. 既然value存放在Thread中,为什么不直接由Thread提供getter/setter接口,而需要额外有一个ThreadLocal类?
我理解此处的value虽然和Thread之间存在映射关系,但是不属于Thread的属性,放在ThreadLocal更多是性能上的考虑,因此由Thread提供getter/setter并不适合。InheritableThreadLocal原理
InheritableThreadLocal中存放的value是当前线程和当前线程创建出来的子线程可见的。其核心源码如下。public class Thread { private void init(ThreadGroup g, Runnable target, String name, long stackSize) { ... Thread parent = currentThread(); ... //将parent的inheritableThreadLocals同步到child if (parent.inheritableThreadLocals != null) this.inheritableThreadLocals = //此处create一个新的ThreadLocalMap对象 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); ... }
由于child.inheritableThreadLocals是新创建的ThreadLocalMap对象,因此在child中再次执行set,不会影响parent。
参考文献
Java ThreadLocal http://tutorials.jenkov.com/java-concurrency/threadlocal.html相关文章推荐
- 通知、block
- java的IO流
- x+y+z=n的正整数解
- 第五次作业
- 五家共井(第1届第3题)
- 实例化子类的时候是否内存也实例化一个父类对象?
- 第四周项目3 猜数字
- aspx ashx
- 2019
- 论如何面对人生抉择
- AdMob 4.4.2 FBIOGET_FSCREENINFO failed,Async pixel transfers not supported
- 安卓学习笔记(三)使用Intent在活动中穿梭
- yii2分页
- 自定义索引条
- codevs1283等差子序列
- ExtJs中getCmp、getDom、Get的区别
- 我的大学啊,奋斗的土壤
- 97. 骑士游历(动规)(未结题)
- 《Linux内核分析》第六周 读书笔记
- AC自动机---病毒侵袭持续中