1、什么是Threadlocal
我们都知道,在多线程情况下,全局共享变量会被备份在各线程中作为副本,各副本数据与主内存要保持一致,一旦修改某个线程的副本数据,主内存及其他线程的副本数据也会被刷新。
而ThreadLocal主要给每个线程提供局部(本地)变量,每个线程都保存有一个属于自己的变量副本,它可以保证访问到的变量属于当前线程。一旦修改,主内存及其他线程不受影响。
ThreadLocal相当于提供了一种线程隔离,在多线程的情况下,将变量与线程相绑定,不受其他线程影响。ThreadLocal给每个线程提供局部(本地)变量,可以保证每个线程访问到的变量属于当前线程,一旦修改,主内存及其他线程不受影响。
2、Threadlocal基本API
New Threadlocal();---创建Threadlocal
set 设置当前线程绑定的局部变量
get 获取当前线程绑定的局部变量
remove() 移除当前线程绑定的变量
3、Threadlocal应用场景
1)设计模式 Spring事务模板类
2)SpringMVC获取httprequest
--tomcat 接收请求,创建一个线程
--servlet 框架处理请求
--SpringMVCServlet 封装httprequest对象,放入当前ThreadLocal中
--AOP拦截请求
--控制器层 ThreadLocal中获取到该httprequest对象
3)AOP LCN分布式事务、分布式服务追踪框架源码
4、Threadlocal底层实现原理
不同线程有不同的ThreadLocalMap,ThreadLocalMap底层由Entry(key,value)组成,key都是threadlocal对象,但是key对应存储的value不一样,从而达到了线程隔离的目的。
ThreadLocal本身不存储值,它只是作为一个 key 来让线程从 ThreadLocalMap获取value。
ThreadLocalMap是线程自带的一个属性,通过get(t)直接获取,并不是来自于ThreadLocal。
ThreadLocalMap可以存放n多个不同的ThreadLocal对象,但是每个ThreadLocal只能缓存一个变量值。
5、强 软 弱引用实现区别
强引用(StrongReference):对象默认关联强引用。被引用关联的对象永远不会被垃圾收集器回收,即使内存溢出,也不会回收。
软引用(SoftReference):软引用关联的对象,只有当系统内存溢出时,才会回收软引用的对象。
弱引用(WeakReference):只被弱引用关联的对象,当垃圾回收机制触发的时候就会被回收。
6、内存泄漏、内存溢出
什么是内存泄漏?
表示在申请内存后,无法释放已申请的内存空间,导致内存被占光,浪费系统内存,从而造成程序运行速度减慢甚至系统崩溃等严重后果。
什么是内存溢出?
申请内存时,没有足够的内存空间供其使用,出现 out of memory(内存溢出)。
如何防御ThreadLocal内存泄漏问题?
① 调用remove方法,将不要的数据移除,避免内存泄漏。将threadlocalmap中的key与threadlocal断开引用
使用完之后及时调用remove方法(强制)
尽量不要使用全局的ThreadLocal(推荐)
② 每次在做set方法的时候会清除之前key为null
③ ThreadLocal对象为弱引用
7、Threadlocal与Synchronized区别
Synchronized与Threadlocal 都可以实现多线程访问,保证线程安全的问题。
A. Synchronized采用当多个线程竞争到同一个资源的时候,最终只能够有一个线程访问,用时间换取线程的安全。
B.Threadlocal在每个线程中都自己独立的局部变量,空间换时间,相互之间都是隔离。相比来说Threadlocal效率比Synchronized效率更高。