ThreadLocal源码解析
2016-06-30 21:35
447 查看
这个类提供了线程变量,这不同于其他的变量,它能在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的。
使用示例:
接下来我们来看看ThreadLocal的源码。
类中的protected方法,一般用于我们给Thread变量赋初始值。
其中有个静态内部类ThreadLocalMap,其中的数据结构如下
此map的key中ThreadLocal为一个弱引用。当ThreadLocal没有强引用时,此key就会变成null被垃圾回收。注意此时value还在,有可能引起内存泄露。只有当调用get或set方法时才能移除。
每个Thread中有这样一个变量
当第一次调用set方法时,会将 threadLocals 赋值
看下createMap方法,会创建ThreadLocalMap,并赋值给线程
其中Entry的下标是通过神奇的0x61c88647数,使得均匀分布在2的n次方的数组上。
再来看下ThreadLocal的get方法。
已当前线程为key取得ThreadLocalMap ,然后在根据Threadlocal实例取得对应的值并返回。
~~~~~~~~~~
ThreadLocal实现时为什么把Map定义在Thread对象里存成Map
而不是定义在ThreadLocal里存成Map
第一种方式在set的时候这么写
Map map = Thread.currentThread().threadLocalMap;
map.put(this,obj);
第二种方式这么写
threadLocalMap.put(Thread.currentThread(),obj);
第二种是多个线程共享一个map,必须处理同步,性能不如第一个高
http://www.cnblogs.com/ilellen/p/4135266.html
使用示例:
public static void main(String[] args) { ThreadLocal<String> str = new ThreadLocal<String>(); str.set("hello word"); System.out.println(str.get()); }
接下来我们来看看ThreadLocal的源码。
protected T initialValue() { return null; }
类中的protected方法,一般用于我们给Thread变量赋初始值。
其中有个静态内部类ThreadLocalMap,其中的数据结构如下
static class Entry extends WeakReference<ThreadLocal> { Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } }
此map的key中ThreadLocal为一个弱引用。当ThreadLocal没有强引用时,此key就会变成null被垃圾回收。注意此时value还在,有可能引起内存泄露。只有当调用get或set方法时才能移除。
每个Thread中有这样一个变量
ThreadLocal.ThreadLocalMap threadLocals = null;
当第一次调用set方法时,会将 threadLocals 赋值
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
看下createMap方法,会创建ThreadLocalMap,并赋值给线程
ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); }
其中Entry的下标是通过神奇的0x61c88647数,使得均匀分布在2的n次方的数组上。
再来看下ThreadLocal的get方法。
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }
已当前线程为key取得ThreadLocalMap ,然后在根据Threadlocal实例取得对应的值并返回。
~~~~~~~~~~
ThreadLocal实现时为什么把Map定义在Thread对象里存成Map
而不是定义在ThreadLocal里存成Map
第一种方式在set的时候这么写
Map map = Thread.currentThread().threadLocalMap;
map.put(this,obj);
第二种方式这么写
threadLocalMap.put(Thread.currentThread(),obj);
第二种是多个线程共享一个map,必须处理同步,性能不如第一个高
其他参考
http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/http://www.cnblogs.com/ilellen/p/4135266.html
相关文章推荐
- 从源码安装Mysql/Percona 5.5
- 浅析Ruby的源代码布局及其编程风格
- asp.net 抓取网页源码三种实现方法
- JS小游戏之仙剑翻牌源码详解
- JS小游戏之宇宙战机源码详解
- jQuery源码分析之jQuery中的循环技巧详解
- 本人自用的global.js库源码分享
- java中原码、反码与补码的问题分析
- ASP.NET使用HttpWebRequest读取远程网页源代码
- PHP网页游戏学习之Xnova(ogame)源码解读(六)
- C#获取网页HTML源码实例
- PHP网页游戏学习之Xnova(ogame)源码解读(八)
- PHP网页游戏学习之Xnova(ogame)源码解读(四)
- 深入理解PHP之源码目录结构与功能说明
- JS小游戏之极速快跑源码详解
- JS小游戏之象棋暗棋源码详解
- android源码探索之定制android关机界面的方法
- 基于Android设计模式之--SDK源码之策略模式的详解
- Android游戏源码分享之2048
- C语言借助EasyX实现的生命游戏源码