您的位置:首页 > 其它

ThreadLocal源码解析

2016-06-30 21:35 447 查看
这个类提供了线程变量,这不同于其他的变量,它能在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的。

使用示例:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源码