文章目录
- 1.ThreadLocal是什么?
- 2.ThreadLocald实现原理&源码解析
- 3.ThreadLocal-内存泄露问题
1.ThreadLocal是什么?
ThreadLocal 是 Java 中的一个线程局部变量类。它提供了一种在多线程环境下,为每个线程独立存储数据的机制。
并且:
ThreadLocal 通过为每个线程创建一个独立的副本来实现线程隔离。每个线程都可以独立地修改和访问自己的副本,而不会影响其他线程的副本。每个线程都可以像访问普通变量一样访问 ThreadLocal 对象,而不必担心线程安全问题。
2.ThreadLocald实现原理&源码解析
ThreadLocal本质来说就是一个·线程内部存储类·,从而让多个线程只操作自己内部的值,从而实现线程数据隔离
基本方法有:
- set(value) 设置值
- get() 获取值
- remove() 清除值
set(value) 设置值
首先获取当前线程,然后获取当前线程的 ThreadLocalMap 对象。如果 ThreadLocalMap 存在,就将当前 ThreadLocal 对象作为键,将值 value 存储到其中;否则,创建一个新的 ThreadLocalMap,并将当前 ThreadLocal 对象和值 value 存储到其中。
/**
* 设置线程局部变量的值。
* @param value 要设置的值
*/
public void set(T value) {
// 获取当前线程
Thread t = Thread.currentThread();
// 获取当前线程的 ThreadLocalMap,用于存储线程局部变量
ThreadLocalMap map = getMap(t);
if (map != null)
// 如果 ThreadLocalMap 存在,则将当前 ThreadLocal 对象作为键,将 value 作为值存储起来
map.set(this, value);
else
// 如果 ThreadLocalMap 不存在,则创建一个新的 ThreadLocalMap,并将当前 ThreadLocal 对象和 value 存储到其中
createMap(t, value);
}
get() 获取值
通过ThreadLocal 对象去取对应的value
首先,获取当前线程并获取其对应的 ThreadLocalMap 对象。如果 ThreadLocalMap 存在,则通过调用 getEntry(this) 方法获取当前 ThreadLocal 对象对应的条目。如果条目存在,则返回条目中存储的值。如果线程局部变量不存在,则调用 setInitialValue() 方法返回初始值。
/**
* 获取线程局部变量的值。
* @return 线程局部变量的值,如果不存在则返回初始值
*/
public T get() {
// 获取当前线程
Thread t = Thread.currentThread();
// 获取当前线程的 ThreadLocalMap,用于存储线程局部变量
ThreadLocalMap map = getMap(t);
if (map != null) {
// 通过 ThreadLocalMap 获取对应的条目
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
// 如果条目存在,则返回条目中存储的值
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
// 如果线程局部变量不存在,则返回初始值
return setInitialValue();
}
remove() 清除值
根据ThreadLocal 删除对
/**
* 从当前线程的 ThreadLocalMap 中移除当前 ThreadLocal 对象对应的条目。
*/
public void remove() {
// 获取当前线程的 ThreadLocalMap
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null) {
// 如果 ThreadLocalMap 存在,则调用 remove(this) 方法移除当前 ThreadLocal 对象对应的条目
m.remove(this);
}
}
3.ThreadLocal-内存泄露问题
什么是内存泄漏:
内存泄漏是指在程序中,不再使用的对象仍然被占用着内存,无法被垃圾回收器回收释放,导致内存占用逐渐增加,最终可能导致内存耗尽或性能下降。
Java对象中的四种引用类型:强引用、软引用、弱引用、虚引用
强引用:最为普通的引用方式,表示一个对象处于有用且必须的状态,如果一个对象具有强引用,则GC并不会回收它。即便堆中内存不足了,宁可出现OOM,也不会对其进行回收

弱引用:表示一个对象处于可能有用且非必须的状态。在GC线程扫描内存区域时,一旦发现弱引用,就会回收到弱引用相关联的对象。对于弱引用的回收,无关内存区域是否足够,一旦发现则会被回收

出现内存泄漏的原因:
-
长期持有:如果在 ThreadLocal 中设置的值
长时间持有,而没有进行及时清理和释放,可能导致内存泄漏。(只要线程不结束,就一直存在) -
线程结束不清理:如果在
线程结束时没有正确地清理 ThreadLocal,可能会导致内存泄漏。因为线程结束后,对应的ThreadLocalMap 对象不会被垃圾回收,其中的ThreadLocal 对象也无法释放。 -
对象强引用:每一个
Thread维护一个ThreadLocalMap,在ThreadLocalMap中的Entry对象继承了WeakReference。其中key为使用弱引用的ThreadLocal实例,value为线程变量的副本

解决办法就是:使用完ThreadLocal后主动 remove 释放 key,value


















