ThreadLocal是为了解决线程间数据共享带来的问题
- 看下Thread, ThreadLocal和ThreadLocalMap之间的关系

- 使用get方法的时候
public T get() {
Thread t = Thread.currentThread(); //当前线程
ThreadLocalMap map = getMap(t); //获取线程中的数据结构ThreadLocalMap
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this); //ThreadLocal为key拿到ThreadLocalMap中的Entry
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value; //拿到Entry中存储的value
return result;
}
}
return setInitialValue();
}
1.拿到当前Thread;
2.拿到当前线程中的数据结构ThreadLocalMap;
3.ThreadLocal作为key获取对应的Entry;
4.取到Entry中的value,就是存储的数据
ThreadLocal和ThreadLocalMap之间的关系
- ThreadLocalMap.Entry继承了WeakReference, 它的key是一个ThreadLocal,所以ThreadLocal的生命周期结束之后,由于软应用,key也就是ThreadLocalMap也会在GC的时候被清除,达到回收内存的目的;这是建立在Thread会被销毁的情况下。
ThreadLocal存在的内存泄漏问题
- 在线程池存在的情况下可能会出现内存溢出的情况,因为线程池中的线程coreSizePool线程在任务结束之后不会被销毁,而是回到空闲队列中。Thread的生命周期比ThreadLocal长很多,这样即使ThreadLocal的生命周期结束,Entry中的value依然是强引用,导致内存无法回收。
如何解决上述问题
- try{}finally{} 关闭资源,threadLocal.remove()方法可以移除ThreadLocal对应的entry。
网友评论