ThreadLocal里面使用了一个存在弱引用的map,当释放掉threadlocal的强引用以后,map里面的value却没有被回收.而这块value永远不会被访问到了. 所以存在着内存泄露. 最好的做法是将调用threadlocal的remove方法.

在threadlocal的生命周期中,都存在这些引用. 看下图: 实线代表强引用,虚线代表弱引用.

每个thread中都存在一个map, map的类型是ThreadLocal.ThreadLocalMap。 Map中的key为一个Threadlocal实例. 这个Map的确使用了弱引用,不过弱引用只是针对key. 每个key都弱引用指向threadlocal. 当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收. 但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用. 只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.
  

所以得出一个结论就是只要这个线程对象被gc回收,就不会出现内存泄露,但在threadLocal设为null和线程结束这段时间不会被回收的,就发生了我们认为的内存泄露。其实这是一个对概念理解的不一致,也没什么好争论的。最要命的是线程对象不被回收的情况,这就发生了真正意义上的内存泄露。比如使用线程池的时候,线程结束是不会销毁的,会再次使用的。就可能出现内存泄露。

PS.Java为了最小化减少内存泄露的可能性和影响,在ThreadLocal的get,set的时候都会清除线程Map里所有key为null的value。所以最怕的情况就是,threadLocal对象设null了,开始发生“内存泄露”,然后使用线程池,这个线程结束,线程放回线程池中不销毁,这个线程一直不被使用,或者分配使用了又不再调用get,set方法,那么这个期间就会发生真正的内存泄露。

划重点-总结一下:

  1. ThreadLocal是什么?
    每个线程在对内存中开辟的一块工作内存,同时把线程的共享数据拷贝了一份放进去,相当于做的本地副本,不会像synchronized一样每次修改都要同步到主内存中
  2. ThreadLocal有什么用?
    • 工作线程的数据交互主要是本地数据和主内存数据的交互,当数据存储在本地内存中,可以大大提高读取效率,避免了线程阻塞造成的cpu的吞吐下降;
    • 在多线程中每个线程中都要维护sesion,可以提高对独有资源的工作效率;
  3. 发生内存泄露原因?
    • synchornized是保证了主内存数据的一致,是时间换空间:通过阻塞一个共享变量,共享一小块内存空间;
    • threadLocal是通过建立线程的副本数据,空间换时间
    • ThreadLocalMap的Key为弱引用,当threadlocal对象被回收(value在ThreadLocalMap调用get、set、remove的时候就会被清除),这时将key设置为null的entry。但是threadlocal一直不会被回收,导致内存的泄露
    1. 如何避免呢?
      其实在调用threalocalMap的get/set方法时,会对key=null的entry(threadlocal对象=null)进行回收,也可以在调用结束时调用remove方法进行释放。
转载地址:https://www.cnblogs.com/onlywujun/p/3524675.html

ThreadLocal什么时候会出现OOM的情况?为什么?相关推荐

  1. Java程序员从阿里拿到offer回来,这些面试题你会吗?

    前不久刚从阿里面试回来,为了这场面试可以说准备了一个半月,做的准备就是刷题和看视频看书充实自己的技术,话说是真难啊,不过还算顺利拿到了offer,有很多面试题我已经记不起来了,这些是当天回家整理好的, ...

  2. Java程序员从阿里面试回来,这些面试题你们会吗?

    前不久刚从阿里面试回来,为了这场面试可以说准备了一个半月,做的准备就是刷题和看视频看书充实自己的技术,话说是真难啊,不过还算顺利拿到了offer,有很多面试题我已经记不起来了,这些是当天回家整理好的, ...

  3. Kafka的精髓全写这本“限量笔记”里了

    前言 大厂面试真题向来是求职者的最佳练兵场,华为在Java开发工程师招聘中有哪些技术性考察和倾向?那今天咱就给大家分享一下近期的华为5面面经! 注:以下所分享的华为面试问题,相关的答案我也整理出来了, ...

  4. 2021Java不死我不倒,吊打面试官系列!

    前言 从3月份开始,打算找工作,一个偶然的机会,拉勾上一个蚂蚁金服的师兄找到我,说要内推,在此感谢姚师兄,然后就开始了蚂蚁金服的面试之旅.把简历发过去之后,就收到了邮件通知,10个工作日联系我,请耐心 ...

  5. 学习SpringBoot:知乎超赞回答:Java如何进阶?分享面经

    前言 Spring 是一个非常流行和成功的 Java 应用开发框架.Spring Security 是 Spring 家族中的一个安全管理框架,提供了一套 Web 应用安全性的完整解决方案.在用户认证 ...

  6. 马士兵内部共享—1658页《Java面试突击核心讲》,面试神技

    "金九银十" 秋招大热门已经到了末尾,为助力广大程序员朋友 "面试造火箭",小编今天给大家分享的便是这份马士兵内部的面试神技--1658页<Java面试突 ...

  7. 全网首发?蚂蚁金服内部共享—1658页《Java面试突击核心讲》

    又是一年一度的 "金九银十" 秋招大热门,为助力广大程序员朋友 "面试造火箭",小编今天给大家分享的便是这份蚂蚁金服内部的面试神技--1658页<Java ...

  8. BAT 大厂Java 面试题集锦之核心篇附参考答案

    核心篇 数据结构与算法 网路:TCP/IP, HTTP 操作系统, 文件, shell, CPU, IO, epoll, 非阻塞IO, 进程/线程/协程,锁 HashMap, ConcurrentHa ...

  9. 不可多得的干货!互联网公司常用分库分表方案汇总!太完整了!

    前言 前几天我上班路上,和小区门口开车的师傅闲聊,发现他们虽然学历不高,但挣钱的途径不少,比如固定接送多位客户,然后能通过朋友圈拓展新客户,而且通过客户口口相传,也能不断拉到生意,算下来每月也能挣1万 ...

最新文章

  1. python如何小写p转换p_Python进阶---python 中字符串大小写转换
  2. 单片机while用法c语言例子,51单片机-C语言之while(!x)的理解
  3. MFC多标签页对话框
  4. 在Tomcat上设置和使用Apache Solr
  5. boot druid 长时间不连接 异常_Spring Boot学习:如何使用Druid数据源
  6. Unity代码里的Position和界面上的Position
  7. 库克警告员工不要泄露公司信息:将全力追查
  8. Compose 1.0 即将发布,你准备好了吗?
  9. 【学习笔记】深度学习理论基础
  10. ai跟随路径_AI教程:如何沿着对象的路径输入文字?
  11. 解决Windows Update错误“80072EFD”
  12. 社交网络叠加直播功能,会产生什么化学反应?
  13. 纯java写2D格斗游戏(一)——界面背景设置及人物的简单设置
  14. 支付宝AR扫福背后的故事
  15. 湖北移动M411A_ZN-S905L3AB-UWE5621DS原机制作语音线刷包
  16. 小程序 和 web 功能对比_小程序官方推出的Kbone,是如何解决Web 端和小程序同构痛点的?...
  17. 求助交通仿真 Netlogo软件
  18. Qt实现Linux下的硬盘空间监测和文件清理
  19. 课后作业——Day5
  20. html中复选文本框标签,JavaScript:HTML中的UI-标签

热门文章

  1. static静态方法(1)——c#静态方法怎么调用非静态方法
  2. python求是不是完数_python求完数
  3. 软件测试标准GBT250,国家标准规范GBT 25063-2010.doc
  4. 面向DevSecOps的编码安全指南|JavaScript篇
  5. 我爱Flask框架之Flask简介与URL和视图介绍
  6. OS第二章五大经典PV
  7. 从零开始社区之路,手把手教你开源自己的Python包
  8. 数字化转型避无可避,PCB行业如何借力采购管理平台“乘风破浪”
  9. Kotlin 中的 appy和with方法
  10. 学习PLC的重要知识点,你知道哪些?