ThreadLocal核心知识

什么是ThreadLocal

全称thread local variable(线程局部变量)功用非常简单,使用场合主要解决多线程中数据因并发产生不一致问题。

ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享,这样的结果是耗费了内存,但大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。

总结起来就是:同个线程共享数据

注意:ThreadLocal不能使用原子类型,只能使用Object类型

核心应用场景

ThreadLocal 用作每个线程内需要独立保存信息,方便同个线程的其他方法获取该信息的场景。

每个线程获取到的信息可能都是不一样的,前面执行的方法保存了信息后,后续方法可以通过ThreadLocal 直接获取到,避免了传参,类似于全局变量的概念,比如用户登录令牌解密后的信息传递(还有用户权限信息、从用户系统获取到的用户名、用户ID)

1
2
3
4
5
6
7
8
9
public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();


LoginUser loginUser = new LoginUser();
loginUser.setId(id);
loginUser.setName(name);
loginUser.setMail(mail);
loginUser.setHeadImg(headImg);
threadLocal.set(loginUser);

ThreadLocal底层源码和原理

  • ThreadLocal中的一个内部类ThreadLocalMap,这个类没有实现map接口,就是一个普通的Java类,但是实现的类似map的功能

  • 每个数据用Entry保存,其中的Entry继承与WeakReference,用一个键值对存储,键为ThreadLocal的引用。

  • 每个线程持有一个ThreadLocalMap对象,每一个新的线程Thread都会实例化一个ThreadLocalMap并赋值给成员变量threadLocals,使用时若已经存在threadLocals,则直接使用已经存在的对象。

ThreadLocal常见核心面试题

P6面试题:ThreadLocal和Synchronized的区别

  • 都是为了解决多线程中相同变量的访问冲突问题
  • Synchronized是通过线程等待,牺牲时间来解决访问冲突
  • ThreadLocal是通过每个线程单独一份存储空间,牺牲空间来解决冲突,
  • 对比Synchronized,ThreadLocal具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问到想要的值

P6面试题:为啥什么ThreadLocal的键是弱引用,如果是强引用有什么问题?

Java中除了基础的数据类型以外,其它的都为引用类型。
而Java根据其生命周期的长短将引用类型又分为强引用 、 软引用 、 弱引用 、 虚引用
正常情况下我们平时基本上我们只用到强引用类型,而其他的引用类型我们也就在面试中,或者平日阅读类库或其他框架源码的时候才能见到

1、强引用 new了一个对象就是强引用 Object obj = new Object();

2、软引用的生命周期比强引用短一些,通过SoftReference类实现,当内存空间足够,垃圾回收器就不会回收它; 当JVM认为内存空间不足时,就会去试图回收软引用指向的对象,也就是说在JVM抛出OutOfMemoryError之前,会去清理软引用对象
主要用来描述一些【有用但并不是必需】的对象
使用场景:适合用来实现缓存,内存空间充足的时候将数据缓存在内存中,如果空间不足了就将其回收掉

3、弱引用是通过WeakReference类实现的,它的生命周期比软引用还要短,在GC的时候,不管内存空间足不足都会回收这个对象
使用场景:一个对象只是偶尔使用,希望在使用时能随时获取,但也不想影响对该对象的垃圾收集,则可以考虑使用弱引用来指向该对象。

ThreadLocal为什么是WeakReference呢?

如果是强引用,即使把ThreadLocal设置为null,但是ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄漏

如果是弱引用
引用ThreadLocal的对象被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。value在下一次ThreadLocalMap调用set、get、remove的时候会被清除。