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(15)-序列
  2. 课后练习----实现窗口的切换
  3. Microsoft Edge 提供快速的 JavaScript 性能
  4. linux命令大全rename,Linux常用命令汇总--rename
  5. 「读懂源码系列2」我从 lodash 源码中学到的几个知识点
  6. inner join 和join的区别_left join、right join和join ???
  7. tomcat热部署 更改类文件不需要重起
  8. mysql sum 慢_故障分析 | MySQL 优化案例 - select count(*)
  9. docker-maven-plugin 推送镜像到 docker-hub
  10. AI Challenger 2018:细粒度用户评论情感分类冠军思路总结
  11. wifi分析仪怎么看哪个信道好_WiFi信道扫描仪:通过NetSpot选择最佳WiFi信道
  12. 联想win7旗舰版忘记开机密码--有效处理办法
  13. 云服务器win系统开热点,云服务器win系统开热点
  14. linux安装teamviewer黑屏,如何在CentOS 7上安装TeamViewer
  15. 职工信息管理系统(链表版)
  16. MySQL在服务里找不到(未卸载)
  17. linux 重启nginx命令
  18. USRP 套件在windows下的快速引入
  19. MySQL数据库之约束
  20. 使用腾讯云clb实现https转发

热门文章

  1. 如何快速深度写论文?
  2. MySQL8.0.11修改root密码
  3. Linux死锁调试之softlockup
  4. Woohoo flash
  5. sql sever使用
  6. Declaration of Interest Statement
  7. (Unity消防演练之灭火功能的前期准备)设计火势控制的脚本
  8. python pandas库详解_Pandas 库的详解和使用补充
  9. 有病毒的u盘文件上传到服务器,还在被u盘病毒困扰?送你15个文件传输网站以及20+u盘工具...
  10. 数值法求解最优控制问题(二)——打靶法