ThreadLocad
底层实现原理1
底层实现原理2
ThreadLocal#ThreadLocalMap内部类实现细节
文章目录
- ThreadLocad
- 底层实现原理1
- 底层实现原理2
- ThreadLocal#ThreadLocalMap内部类实现细节
- Threadlocal基本API
- 哪些地方使用Threadlocal
- Threadlocal 底层实现原理
- 底层实现原理1
- 底层实现原理2
- 为什么线程缓存的是 ThreadlocalMap 对象
- 谈谈强、软、弱、虚引用 区别
- Threadlocal 为何引发内存泄漏问题
- 如何防御 Threadlocal 内存泄漏问题
- Threadlocal 采用弱引用而不是强引用
Threadlocal提供了线程本地变量,它可以保证访问到的变量属于当前线程,每个线程都保存了一个变量的副本,每个线程的变量不同,Threadlocal相当于提供了一种线程隔离,将变量与线程绑定
Threadlocal适用于在多线程的情况下,可以实现传递数据,实现数据隔离
Threadlocal提供给我们每个线程缓存局部变量
Threadlocal基本API
- NEW Threadlocal(); --创建Threadlocal
- set 设置当前线程绑定的局部变量
- get 获取当前线程绑定的局部变量
- remove() 移除当前线程绑定的变量
哪些地方使用Threadlocal
- Spring 事务模板类
- 获取 HttpRequest
- Aop 调用链
javaweb项目,tomcat接收请求
创建一个线程接受请求—aop目标方法
- 设计模式 模板方法—
- SpringMVC 获取HttpRequest 对象+==SPringMVC封装 将HttpRequest 对象缓存在当前线程中
javaweb中的SpringMVC
- tomcat接受请求.创建一个线程
- servlet框架处理请求
- SpringMVC servlet 做了一层封装,封装HttpRequest 对象放入当前的Threadlocal
- AOP拦截请求
-
控制层—Threadlocal获取到HttpRequest
最终都是同一个线程子啊处理,(中间经过n多个不同的方法)
AOP拦截器请求–AOP 缓存一个变量Threadlocal中
–控制层获取到该变量
分层架构
控制层 --将变量缓存到Threadlocal中
业务逻辑层 — 从Threadlocal 获取到该变量
DB层
Threadlocal 底层实现原理
底层实现原理1
底层实现原理2
- 在每个线程中都有自己独立的ThreadlocalMap对象,中Entry对象
- 如果在当前线程对应的ThreadlocalMap对象为空的情况下,则创建ThreadlocalMap对象,并且赋值键值对
key为当前的new Threadlocal 对象 value就是object变量值
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAnYldHL0FWby9mZvwFN4ETMfdHLkVGepZ2XtxSZ6l2clJ3LcV2Zh1Wa9M3clN2byBXLzN3btgHL9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsQTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5yNzEzN4YjMkFmN0EzN1IWNzYzXyEDNxITM4IzLcBTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
为什么线程缓存的是 ThreadlocalMap 对象
Threadlocal可以存放n多个不同的Threadlocal对象
每个Threadlocal对象只能缓存一个变量值
ThreadLocalMap <ThreadLocal 对象,value> threadLocalMap
ThreadLocal.get();
threadLocalMap.get(ThreadLocal)-----缓存变量值
谈谈强、软、弱、虚引用 区别
强引用: 当内存不足时,JVM 开始进行 GC(垃圾回收),对于强引用对象,就算是出现了 OOM 也不会对该对象进行回收,死都不会收。
软引用:当系统内存充足的时候,不会被回收;当系统内存不足时,它会被回收,软引用通 常用在对内存敏感的 程序中,比如高速缓存就用到软引用,内存够用时就保留,不够时就 回收
弱引用:弱引用需要用到
java.lang.ref.WeakReference
类来实现,它比软引用的生存周期更短。 对于只有弱引用的对象来说,只要有垃圾回收,不管 JVM 的内存空间够不够用,都会回收 该对象占用的内存空间。
System.gc() 可以清理弱引用
虚:虚引用需要
java.lang.ref.Phantomreference
类来实现。顾名思义,虚引用就是形同虚设。 与其它几种引用不同,虚引用并不会决定对象的声明周期。
Threadlocal 为何引发内存泄漏问题
补充概念: 什么是内存泄漏问题
内存泄漏: 表示就是我们程序员申请了内存,但是该内存一直无法释放
内存泄漏溢出问题:
申请内存时,发现申请内存不足,就会报错,内存溢出的问题
因为每个线程中都有自己独立的
ThreadLocalMap
对象,key为
ThreadLocal
,
value
是为变量值
key为ThreadLocal 最为Entry对象key,为弱引用,当ThreadLocal指向null的时候,Entry对象中的key变为null…GC如果没有清理垃圾时,则该对象一直无法被垃圾机制回收,一直占用到了系统内存,有可能会发生内存泄漏的问题。
如何防御 Threadlocal 内存泄漏问题
- 自己调用remove方法将不要的数据移除避免内存泄漏的问题
- 每次在做set方法的时候 清除之前的key为NULL
- Threadlocal为弱引用
Threadlocal 采用弱引用而不是强引用
1.如果 key 是为强引用: 当我们现在将 ThreadLocal 的引用指向为 null,但是 每个线程中有自己独立 ThreadLocalMap 还一直在继续持有该对象,但是我们 ThreadLocal 对象不会被回收,就会发生 ThreadLocal 内存泄漏的问题。
2.如果 key 是为弱引用: 当我们现在将 ThreadLocal 的引用指向为 null,Entry 中的 key 指向为 null,但是 下次调用 set 方法的时候,会根据判断如果 key 空的情况下,直接删除,避免了 Entry 发生 内存泄漏的问题。
3.不管是用强引用还是弱引用都是会发生内存泄漏的问题。 弱引用中不会发生 ThreadLocal 内存泄漏的问题。
4.但是最终根本的原因 Threadlocal 内存泄漏的问题,产生于 ThreadLocalMap 与 我们当前线程的生命周期一样,如果没有手动的删除的情况下,就有可能会发生内存泄漏的 问题。
(强制)在代码逻辑中使用完Threadlocal,都要调用remove方法,及时清理
(推荐)尽量不要使用全局的Threadlocal