好早之前就知道ThreadLocal,但是一直都没有用过,总感觉之前很明白,但是今天在用的时候突然间觉得不明白了,所以还是好好研究了研究。
下面列举了几个知识点,用于说明为什么要存在ThreadLocal:
1,ThreadLocal在用法上是提供了一种方法见传递的另外一种方式:例如之前你需要把一个变量在各个方法间传来传去,现在可以把需要传递的变量放到ThreadLocal中,
如在类中定义一个static ThreadLocal threadLocal = new ThreadLocal();
上面的这种做法似乎是不符合面向对象编程的原则,但是再有些情况下传递一些不必要的参数让代码更加的难看(我今天其实也就是出于这种原因),因此ThreadLocal是提供了另外一种编码的方式。
2,ThreadLocal在具体实现上其实是把你需要保存的变量存放到了当前线程的上下午信息内,所以也就只对这个线程有影响。如jdk中的ThreadLocal实现思路如下:
首先看一下源代码:
ThreadLocal的set方法:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //ThreadLocalMap 类型的map其实放到当前Thread中的一个Map(这个Map和java.util.Map没有继承上的关系)类型的变量
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
下面的两个方法可以印证上面的注释:
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
3,ThreadLocal变量的生命周期:
ThreadLocal变量的生命周期和线程的生命周期一样,线程结束ThreadLocal变量也就销毁了,同时也要注意的是线程没有销毁那么ThreadLocal也就一直存在,这个在应用线程池的情况下需要注意一下,不要让ThreadLocal弄巧成拙。
同时针对上面提到的ThreadLocal和线程池,ThreadLocal还可以提供变量缓存的作用:即线程池中的线程没有销毁的话,那么线程所持有的变量(set方法set进去的变量)也就会一直存在。
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
4,虽然使用ThreadLocal不会造成内存泄露,但是我们在使用完后还是调用一下remove方法:
具体我还没搞清楚,如下链接我感觉写的很好:
http://liuinsect.iteye.com/blog/1827012
http://hubingforever.blog.163.com/blog/static/17104057920109133152446/