什么是ThreadLocal?
ThreadLlocal 是 Java 中所提供的线程本地存储机制,可以利用该机制将数据缓存在某个线程内部,该线程可以在任意时刻、任意方法中获取缓存的数据。
可以看看一个简单的Demo:
public class ThreadLocalDemo {
public static ThreadLocal<String> s = new ThreadLocal<>();
public static void main(String[] args) {
s.set("Harmony");
String s1 = ThreadLocalDemo.s.get("");
}
}
ThreadLocal 底层原理
Threadlocal底层是通过 ThreadloalMap 来实现的。
每 Thread对象(注意不是ThreadLocal)中都存在 ThreadlocaMap,Map的key为 Threadlocal对象,Map的value为需要缓存的值。
我们可以很清晰的看到,在ThreadLocal类中的确是有一个 ThreadLocalMap 作为静态内部类,但是它的使用却是在线程中(Thread里面)!
我们可以看看它的 set()、get() 方法
// ThreadLocal类
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocal.ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
内存泄漏(线程池)
如果在线程池中使用ThreadLocal会造成内存泄漏。
当ThreadLocal对象使用完之后,应该要把设置的 key、value (即:Entry对象)进行回收,但线程池中的线程不会回收,而线程对象是通过强引用指向 ThreadLocalMap,ThreadLocalMap也是通过强引用指向Entry对象,线程不被回收,Entry对象也就不会被回收,从而出现内存泄漏!!!
解决办法
在使用了ThreadLocal对象之后,手动调用ThreadLocal的 remove()方法,手动清除Entry对象!
使用场景
Threadlocal经典的应用场景就是连接管理
一个线程持有一个连接,该连接对象可以在不同的方法之间进行传递,线程之间不共享同一个连接。