ThreadLocal
一、ThreadLocal是什么?线程本地变量 数据隔离
1.ThreadLocal用来存放线程本地变量,提供了一种线程安全的方式,用来避免数据共享(线程变量隔离)。
ThreadLocal<T>其实是与线程绑定的一个变量。
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。
1)Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
2)Synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本
,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。
private static
修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都会被回收。![](https://img2022.cnblogs.com/blog/541191/202208/541191-20220822171147363-2047723679.png)
get() 获取变量
remove() 移除变量
initialValue() 返回变量的初始值
二、线程池中使用threadlocal为什么容易造成内存泄漏?(Thread 一直不终结的话,value 对象就会一直存在于内存中,也就导致了内存泄漏。)解决方法:调用remove()方法
1.ThreadLocal 在没有外部强引用时,发生 GC 时会被回收,那么 ThreadLocalMap 中保存的 key 值就变成了 null,而 Entry 又被 threadLocalMap 对象引用,threadLocalMap 对象又被 Thread 对象所引用,那么当 Thread 一直不终结的话,value 对象就会一直存在于内存中,也就导致了内存泄漏,直至 Thread 被销毁后,才会被回收。
简单来说,就是ThreadLocalMap中的key被GC回收了,而value值还在内存中。
2.解决办法:
1)调用remove方法手动删除threadLocal的数据。三、ThreadLocal使用场景
每个线程需要自己独立的实例且该实例需要在多个方法中使用。
1. 多线程环境中为每一个jdbc分配一个Connection连接,使用ThreadLocal去保存连接,这样就保证了每个线程在自己的连接上操作数据库,不会出现A线程关闭B的Connnection操作。
2. Web中的session管理时,可以使用ThreadLocal记录每个线程的Session,这样保证每个线程都可以获取自己的session。
3. 解决线程安全问题,对于需要进行线程隔离的变量,可以使用ThreadLocal存储,确保线程隔离。
4.Spring 事务管理器采用了 ThreadLocal。
5.Spring MVC 的 RequestContextHolder 的实现使用了 ThreadLocal。
四、引用类型
引用类型 | 回收时间 | 使用场景 | 生存时间 |
强引用 | 从来不会 | 普通的引用Object o = new Object() |
JVM停止运行时终止 |
软引用 | 当内存不足时 | 内存敏感的高速缓存 | 内存不足时终止 |
弱引用 | 正常GC时 | 对象缓存(ThreadLocal等) | 垃圾回收后终止 |
虚引用 | 正常GC时 | 跟踪对象被回收的状态 | 垃圾回收后终止 |