点击上方蓝色“程序猿DD”,选择“设为星标”

回复“资源”获取独家整理的学习资料!

ThreadLocal的原理和实现

ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。

一个线程内可以存在多个 ThreadLocal 对象,所以其实是 ThreadLocal 内部维护了一个 Map ,这个 Map 不是直接使用的 HashMap ,而是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类。

而我们使用的 get()、set() 方法其实都是调用了这个ThreadLocalMap类对应的 get()、set() 方法。这个储值的Map并非ThreadLocal的成员变量,而是java.lang.Thread 类的成员变量。ThreadLocalMap实例是作为java.lang.Thread的成员变量存储的,每个线程有唯一的一个threadLocalMap。

这个map以ThreadLocal对象为key,”线程局部变量”为值,所以一个线程下可以保存多个”线程局部变量”。对ThreadLocal的操作,实际委托给当前Thread,每个Thread都会有自己独立的ThreadLocalMap实例,存储的仓库是Entry[] table;Entry的key为ThreadLocal,value为存储内容;因此在并发环境下,对ThreadLocal的set或get,不会有任何问题。

由于Tomcat线程池的原因,我最初使用的”线程局部变量”保存的值,在下一次请求依然存在(同一个线程处理),这样每次请求都是在本线程中取值。所以在线程池的情况下,处理完成后主动调用该业务treadLocal的remove()方法,将”线程局部变量”清空,避免本线程下次处理的时候依然存在旧数据。

ThreadLocal为什么要使用弱引用和内存泄露问题

在ThreadLocal中内存泄漏是指ThreadLocalMap中的Entry中的key为null,而value不为null。因为key为null导致value一直访问不到,而根据可达性分析导致在垃圾回收的时候进行可达性分析的时候,value可达从而不会被回收掉,但是该value永远不能被访问到,这样就存在了内存泄漏。

如果 key 是强引用,那么发生 GC 时 ThreadLocalMap 还持有 ThreadLocal 的强引用,会导致 ThreadLocal 不会被回收,从而导致内存泄漏。弱引用 ThreadLocal 不会内存泄漏,对应的 value 在下一次 ThreadLocalMap 调用 set、get、remove 方法时被清除,这算是最优的解决方案。

Map中的key为一个threadlocal实例.如果使用强引用,当ThreadLocal对象(假设为ThreadLocal@123456)的引用被回收了,ThreadLocalMap本身依然还持有ThreadLocal@123456的强引用,如果没有手动删除这个key,则ThreadLocal@123456不会被回收,所以只要当前线程不消亡,ThreadLocalMap引用的那些对象就不会被回收,可以认为这导致Entry内存泄漏。

如果使用弱引用,那指向ThreadLocal@123456对象的引用就两个:ThreadLocal强引用和ThreadLocalMap中Entry的弱引用。一旦ThreadLocal强引用被回收,则指向ThreadLocal@123456的就只有弱引用了,在下次gc的时候,这个ThreadLocal@123456就会被回收。

虽然上述的弱引用解决了key,也就是线程的ThreadLocal能及时被回收,但是value却依然存在内存泄漏的问题。当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收.map里面的value却没有被回收.而这块value永远不会被访问到了.

所以存在着内存泄露,因为存在一条从current thread连接过来的强引用.只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.所以当线程的某个localThread使用完了,马上调用threadlocal的remove方法,就不会发生这种情况了。

另外其实只要这个线程对象及时被gc回收,这个内存泄露问题影响不大,但在threadLocal设为null到线程结束中间这段时间不会被回收的,就发生了我们认为的内存泄露。最要命的是线程对象不被回收的情况,这就发生了真正意义上的内存泄露。比如使用线程池的时候,线程结束是不会销毁的,会再次使用,就可能出现内存泄露。

往期推荐

干掉Navicat:正版 MySQL 官方客户端真香!

赠书:算法与数据中台“网约车业务实践”

HTTPS证书知识扫盲

这样配置,让你的 IDEA 好用到飞起来!

中国工商银行已使用OceanBase!

陌陌开源合规审计平台 Bombus

专注于「开发者」综合成长的深度星球

限时优惠进行中

热门分享内容回顾

- 社会人0924期:新手架构最容易忽略的点!

- 技术人0725期:说说我在银行科技部门学到的东西!

面试:说说你对 ThreadLocal 的认识?相关推荐

  1. threadlocal存连接对象的目的_面试官:知道ThreadLocal嘛?谈谈你对它的理解?

    在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余. 这篇文章主要从以 ...

  2. 淘宝面试:说一下 ThreadLocal 的原理?网友:现在面试不看源码不行啊~

    作者 | 天才程序YUAN 来源 | https://urlify.cn/NRJvy2 前言 上周我侥幸通过美团一面(点击查看一面过程),岗位是java后端开发工程师.美团面试官给我进行了二面.面试过 ...

  3. 拼多多面试官没想到ThreadLocal我用得这么溜,人直接傻掉

    点赞再看,养成习惯,微信搜一搜[敖丙]关注这个互联网苟且偷生的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列 ...

  4. Java面试必问:ThreadLocal终极篇

    若有收获,请记得分享和转发哦 开场白 张三最近天气很热心情不是很好,所以他决定出去面试跟面试官聊聊天排解一下,结果刚投递简历就有人约了面试. 我丢,什么情况怎么刚投递出去就有人约我面试了?诶...真烦 ...

  5. 美团面试,问了ThreadLocal原理,这个回答让我通过了

    前言 上周我侥幸通过美团一面(点击查看一面过程),岗位是java后端开发工程师.美团面试官给我进行了二面.面试过程中他问了ThreadLocal原理(上次问线程池,这次问ThreadLocal,美团爸 ...

  6. threadlocal get为空_面试常见知识点:ThreadLocal

    老套路,先列举下关于ThreadLocal常见的疑问,希望可以通过这篇学习笔记来解决这几个问题: ThreadLocal是用来解决什么问题的? 如何使用ThreadLocal? ThreadLocal ...

  7. 弱引用使用场景桌面_面试|再次讲解Threadlocal使用及其内存溢出

    ThreadLocal彻底详解 整理本文主要是想帮助大家完全消化面试中常见的ThreadLocal问题.希望读懂此文以后大家可以掌握: 简单介绍原理 ThreadLocal使用案例场景 Threadl ...

  8. JAVA基础系列:ThreadLocal

    1. 思路 什么是ThreadLocal? ThreadLocal类顾名思义可以理解为线程本地变量.也就是说如果定义了一个ThreadLocal,每个线程往这个ThreadLocal中读写是线程隔离, ...

  9. 互联网java工程师面试突击第三季知识点总结

    目录 Java集合包 01. HashMap的底层数据结构是什么? 02. JDK1.8中对hash算法和寻址算法是如何优化的? 03.HashMap是如何解决hash碰撞问题的? 04.说说Hash ...

  10. 备战面试日记(1.3) - (Java多线程.JUC)

    本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2021.12.29 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. ...

最新文章

  1. 文件管理器android实现,Android开发之简单文件管理器实现方法
  2. postman模拟登录接口
  3. java中XPATH操作xml,非常便捷
  4. 浅谈SCOM Agent的心跳响应机制
  5. 最新战火互娱JS逆向分析实战教程
  6. 忽略字母大小写情况下统计字符出现的次数
  7. 大样本OLS模型假设及R实现
  8. Reading Note(4)——面向关系型数据库的哈希连接加速器
  9. 地球人都在玩跨境电商
  10. 简述网桥的特点_网桥的工作原理和特点是什么呢?
  11. 用PE安装win11系统
  12. java中循环里使用throw new抛出异常问题
  13. [转]int转string string转int
  14. 三维视觉论文阅读:RAFT2020双目光流
  15. 甲骨文公司 Oracle
  16. jenkins的应用
  17. 监理考试用计算机,监理工程师考试用什么计算器
  18. C语言中的输出99乘法表4种方法
  19. 云服务器加固系统,云服务器加固
  20. Qt官方示例-数字时钟

热门文章

  1. 5107LiveChatCode
  2. 如何使用SMTPDiag 工具
  3. linux qemu 报错 Unable to reserve 0xfffff000 bytes of virtual address space at 0x1000 解决方法
  4. python socket select 错误 Filedescriptor out of range in select 解决方法
  5. python3 字符串 转 整型
  6. golang go build 报错 import cycle not allowed
  7. python3 获取异常类型
  8. python3 元组 tuple 操作
  9. linux socket SO_KEEPALIVE选项
  10. Linux7 下重新安装YUM