代码编织梦想

Threadlocal相关问题

核心问题

​ 1、 什么是ThreadLocal?核心方法有哪些?

​ 2、使用 拦截器 + ThreadLocal 处理鉴权的整体流程是什么样的?

​ 3、代码编写实现流程有哪些?

面试相关

ThreadLocal内存泄漏问题

​ 1)、ThreadLocal的实现原理

​ 2)、内存泄漏原因

​ 3)、为什么ThreadLocalMap中的key使用弱引用而不是强引用?

​ 4)、正确使用姿势

问题解析

1、 什么是ThreadLocal?核心方法有哪些?

​ 原理:每个线程有一个与之绑定的容器:Map,这个Map中保存着当前线程的所有的本地变量,这个Map

​ 叫ThreadLocalMap,这个map的键为当前ThreadLocal对象,值为放进去的值

  • 线程内部的存储类,赋予了线程存储数据的能力。

  • 线程内调用get方法都可以从ThreadLocal中获取同一个对象。

  • 多个线程中ThreadLocal数据相互隔离

  • threadlocal核心方法有三个:set(存储数据)、get(获取数据)、remove(删除数据,避免内存溢出)

    ThreadLocal threadLocal = new ThreadLocal();
    threadLocal.set() //将数据绑定到当前线程
    threadLocal.get() //从当前线程中获取数据

    threadLocal.remove() //从当前线程删除数据

2、使用 拦截器 + ThreadLocal 处理鉴权的整体流程是什么样的?

在这里插入图片描述

在这里插入图片描述

3、代码编写实现流程有哪些?

​ 1)、编写ThreadLocal工具类,提供线程存储和获取对象的方法

​ 2)、拦截器解析token验证通过后,将对象存入Threadlocal中

​ 3)、修改各个Controller方法,从ThreadLocal中获取当前登录用户对象

​ 4)、拦截器的afterCompletion中调用remove方法进行threadlocal数据清空,避免内存溢出

拓展:ThreadLocal内存泄漏问题

1、ThreadLocal的实现原理

​ 每一个Thread维护一个ThreadLocalMap,key为使用弱引用的ThreadLocal实例,value为线程变量的副本。这些对象之间的引用关系如下(实心箭头表示强引用,空心箭头表示弱引用):

在这里插入图片描述

2、内存泄漏原因:

ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,Key(ThreadLocal)势必会被GC回收,这样就会导致ThreadLocalMap中key为null, 而value还存在着强引用,只有thead线程退出以后,value的强引用链条才会断掉。

但如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:

Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value

这就就会永远无法回收,造成内存泄漏。

3、为什么ThreadLocalMap中的key使用弱引用而不是强引用?

如果key 使用强引用:当ThreadLocalMap的key为强引用回收ThreadLocal时,因为ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄漏。

如果key使用弱引用:当ThreadLocalMap的key为弱引用回收ThreadLocal时,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。当key为null,在下一次ThreadLocalMap调用set(),get(),remove()方法的时候会被清除value值。使用弱引用可以让GC回收方面多一层保障:弱引用ThreadLocal不会内存泄漏,对应的value会在下一次ThreadLocalMap调用set(),get(),remove()的时候会被清除。因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用

但是,当key为null后,之后再也没有调用过set()、get()、remove()方法,这样就会使value一直不会被回收

4、正确使用姿势:

  • 每次使用完ThreadLocal都调用它的remove()方法清除数据
  • 将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉 。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_59466355/article/details/129630725

什么是多线程?如何实现多线程?_beidaol的博客-爱代码爱编程_多线程

【转】什么是线程安全?怎么实现线程安全? 什么是进程?什么是线程?什么是线程安全?添加一个状态呢?如何确保线程安全?synchronizedlock 转自: https://blog.csdn.net/

java多线程超详解_weixin_44797490的博客-爱代码爱编程_java多线程

引言 随着计算机的配置越来越高,我们需要将进程进一步优化,细分为线程,充分提高图形化界面的多线程的开发。这就要求对线程的掌握很彻底。 那么话不多说,今天本帅将记录自己线程的学习。 程序,进程,线程的基本概念+并行与并发:

多线程面试题(值得收藏)_梦澤羽的博客-爱代码爱编程_多线程面试题

史上最强多线程面试47题(含答案),建议收藏 金九银十快到了,即将进入找工作的高峰期,最新整理的最全多线程并发面试47题和答案总结,希望对想进BAT的同学有帮助,由于篇幅较长,建议收藏后细看~ 1、并发编程三要素? 1

万字图解Java多线程-爱代码爱编程

前言 授权Java面试者精选独家原创发布 java多线程我个人觉得是javaSe中最难的一部分,我以前也是感觉学会了,但是真正有多线程的需求却不知道怎么下手,实际上还是对多线程这块知识了解不深刻,不知道多线程api的应用场景,不知道多线程的运行流程等等,本篇文章将使用实例+图解+源码的方式来解析java多线程。 文章篇幅较长,大家也可以有选择的看

Java 多线程编程基础(详细)-爱代码爱编程

Java多线程编程基础 1. 进程与线程2. 多线程实现2.1 Thread类实现多线程2.2 Runnable接口实现多线程2.3 Callable接口实现多线程2.3 多线程运行状态3. 多线程常用操作方法3.1 线程的命名和获取3.2 线程休眠3.3 线程中断3.4 线程强制执行3.5 线程让步3.6 线程优先级4. 线程的同步和锁死4.1