ThreadLocal 作用
一般创建的每一个变量所有线程均可以访问和修改,为了实现每一个线程有自己独有的变量,ThreadLocal 就可以用来解决这种问题
自己的理解:
相当于在一个类中定义了一个独有的线程 static final,这个线程中存储了独有的变量 和数据,相当于某一个类下的全局变量容器,可以存放一些想要的数据,不论是主线程还是其他线程在 执行过程中访问到的都是相同的内容,一旦修改,那么所有访问到这个线程的内容也都将更改。
但 ThreadLocal 如果使用不当会造成内存泄漏的问题,内存泄漏积攒多了就可能造成内存溢出,从而程序崩溃出错。
内存泄漏
一些已经无用的数据一直存放在内存中,又无法被回收,导致一直有一部分无法使用的数据占据内存的一部分。
内存溢出
当无法继续申请新的内存空间时,就会出现内存溢出,原因可能是有太多的数据都放到了内存中,导致内存已经被占满了,或者是上面内存泄漏的数据太多,之后导致内存空间越来越少。直至内存溢出,无法再申请内存。
ThreadLocal 会发生内存泄漏的前提条件
- ThreadLocal 引用被设为null 后面没有 set, get, remove 操作
- 线程一直运行不停止(线程池)
- 触发垃圾回收(Minor GC或Full GC)
为了避免内存泄漏的使用原则
- ThreadLocal 申明为 private static final (private final 使得对象不被其他对象引用和修改 static 使得对象只有程序结束时才被回收)
- ThreadLocal 使用后调用 remove 方法,直接移除。
总结:
提供了 get set remove 三个方法,在不必要时需要 使用remove 去除数据,以免造成累计的无用数据太多而且一直占用内存造成内存泄漏,过多时可能会造成内存溢出,不够用。
ThreadLocal 定义示例
public class MyClass {
private static final ThreadLocal<String> A_THREAD_OF_MINE = new ThreadLocal<>();
public void test(){
MyClass.A_THREAD_OF_MINE.set("the first time");
}
public void clearData(){
MyClass.A_THREAD_OF_MINE.remove();
}
}
如果需要在其他类中调用则修改为 public 定义
使用spring 中的ThreadLocal 关键点示例
import org.springframework.core.NamedInheritableThreadLocal;
public class UserInfoHolder {
private static final ThreadLocal<UserInfo> USER_INFO_HOLDER = new NamedInheritableThreadLocal<>("myThreadLocal1");
// ...........
}