天天看点

ThreadLocad--概讲

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

  1. NEW Threadlocal(); --创建Threadlocal
  2. set 设置当前线程绑定的局部变量
  3. get 获取当前线程绑定的局部变量
  4. remove() 移除当前线程绑定的变量

哪些地方使用Threadlocal

  1. Spring 事务模板类
  2. 获取 HttpRequest
  3. Aop 调用链

javaweb项目,tomcat接收请求

创建一个线程接受请求—aop目标方法

  1. 设计模式 模板方法—
  2. 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​​

  1. 在每个线程中都有自己独立的ThreadlocalMap对象,中Entry对象
  2. 如果在当前线程对应的ThreadlocalMap对象为空的情况下,则创建ThreadlocalMap对象,并且赋值键值对

key为当前的new Threadlocal 对象 value就是object变量值

ThreadLocad--概讲

为什么线程缓存的是 ThreadlocalMap 对象

Threadlocal可以存放n多个不同的Threadlocal对象

每个Threadlocal对象只能缓存一个变量值

ThreadLocalMap <ThreadLocal 对象,value> threadLocalMap

ThreadLocal.get();

threadLocalMap.get(ThreadLocal)-----缓存变量值

谈谈强、软、弱、虚引用 区别

强引用: 当内存不足时,JVM 开始进行 GC(垃圾回收),对于强引用对象,就算是出现了 OOM 也不会对该对象进行回收,死都不会收。

软引用:当系统内存充足的时候,不会被回收;当系统内存不足时,它会被回收,软引用通 常用在对内存敏感的 程序中,比如高速缓存就用到软引用,内存够用时就保留,不够时就 回收

ThreadLocad--概讲
ThreadLocad--概讲

弱引用:弱引用需要用到​

​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如果没有清理垃圾时,则该对象一直无法被垃圾机制回收,一直占用到了系统内存,有可能会发生内存泄漏的问题。

ThreadLocad--概讲

如何防御 Threadlocal 内存泄漏问题

  1. 自己调用remove方法将不要的数据移除避免内存泄漏的问题
  2. 每次在做set方法的时候 清除之前的key为NULL
  3. 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

ThreadLocad--概讲