ThreadLocal:与其说可以用来减少线程内部参数传递,不如说是提供了维护线程内部上下文的一种方式。
其底层实现只是维护了一个Key为当前线程的Entry表。所以它是线程安全的,存储的值可以认为是该线程的局部变量了。
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
测试类
public class ThreadLocalTest {
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
threadLocal.set("hello");
say();
say2();
}
public void say(){
System.out.println(threadLocal.get());
threadLocal.set("java");
}
public void say2(){
System.out.println(threadLocal.get());
}
}.start();
}
}
hello
java
为什么要使用弱引用?
key 使用强引用:引用ThreadLocal的对象(引用对象)被回收了,但是ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄漏。
然而,即使将key设计成弱引用,也依然存在内存泄漏的场景。
弱引用:引用ThreadLocal的对象(引用对象)被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。而value强引用却没有回收。所以,针对于这种情况,ThreadLocal自身会有保护措施,在某些方法内会删除key为null的值。但我们自己在使用的时候,也要在finally进行释放。。