一、什么是ThreadLocal:
ThreadLocal提供了线程本地变量,它可以保证访问到的变量属于当前线程,每个线程都保存了一个变量副本,每个线程的变量都不同。ThreadLocal相当于提供了一种线程隔离,将变量与线程相绑定。
ThreadLocal适用于在多线程的情况下,可是实现传递数据,实现线程隔离
二、Threadlocal 核心API:
1.set 设置当前线程绑定的局部变量
2.get 获取当前线程绑定的局部变量
3.remove 移除当前线程绑定的变量
Threadlocal简单用法
public class Test {
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
threadLocal.set("值");
System.out.println("成功设置threadLocal");
});
thread.start();
thread.join();
System.out.println(Thread.currentThread().getName() + "," + threadLocal.get());
}
}
子线程在ThreadLocal中存放局部变量,但是获取的时候是主线程,所以无法获取
三、Threadlocal 与Synchronized
1.共同特征:都可以解决线程安全问题
2.ThreadLocal占内存、Synchronized不是很占内存
Synchronized 当多个线程同时共享到同一个全局变量的时候,只能有一个线程对该变量做修改操作,缺陷是效率非常低,以时间换空间
ThreadLocal 每个线程都有独立的缓存的局部变量,以空间换时间的方式提高效率
四、Threadlocal原理分析
1.在每个线程中都有自己独立的ThreadlocalMap对象
2.如果当前线程对应的ThreadlocalMap对象为空的情况下,就会创建该ThreadlocalMap对象,并且赋值键值对
key为当前new ThreadLocal()对象,value就是为object变量值
五、Threadlocal产生内存泄漏问题
因为每个线程都有自己独立的ThreadLocalMap对象,key为ThreadLocal,value 是为变量值。key为ThreadLocal 作为Entity对象的key,为弱引用,当ThreadLocal 指向为null的时候,Entity对象中的key变为null,该对象一直无法被垃圾回收机制回收,一直占有系统的内存,有可能会发生内存泄漏问题。
Threadlocal内存泄漏的根本原因产生于ThreadLocalMap与我们当前线程的生命周期一样,如果没有手动删除的情况下,就有可能发生内存泄漏问题
六、如何防御Threadlocal内存泄漏问题
1.可以自己调用remove方法将不要的数据移除避免内存泄漏的问题,
2. 每次在做set方法的时候会清楚之前 key为null
public class Test {
private static ThreadLocal threadLocal = new ThreadLocal<String>();
public static void main(String[] args) {
threadLocal.set("值");
threadLocal.remove();
threadLocal = null;
System.gc();
Thread thread = Thread.currentThread();
threadLocal.get();
}
}