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方法,那么这个期间就会发生真正的内存泄露。

转载地址:https://www.cnblogs.com/onlywujun/p/3524675.html

ThreadLocal什么时候会出现OOM的情况?为什么?的更多相关文章

  1. Java OOM 常见情况

    Java OOM 常见情况 原文:https://blog.csdn.net/qq_42447950/article/details/81435080 1)什么是OOM?  OOM,全称“Out Of ...

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

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

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

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

  4. 2019 Java面试题

    马上又是一个金九银十的招聘旺季,小编在这里给大家整理了一套各大互联网公司面试都喜欢问的一些问题或者一些出场率很高的Java面试题,给在校招或者社招路上的你一臂之力. 首先我们需要明白一个事实,招聘的一 ...

  5. 2019Java常见面试上

    一.开场白简单的介绍一下自己的工作经历与职责,在校或者工作中主要的工作内容,主要负责的内容:(你的信息一清二白的写在简历上,能答出来的最好写在上面,模棱两可不是很清楚的最好不要写,否则会被问的很尴尬) ...

  6. java——比较难和底层的面试题

    链接地址:https://mp.weixin.qq.com/s/lnbCysCQgfjF_kcB83KQZg 这是一个在线教育机构的文章,感觉大部分都不会,太难了. 一.自我介绍 二.多线程相关: 线 ...

  7. java面试题(目录版)

    在https://www.cnblogs.com/marsitman/p/9539369.html  根据自己以往的面试经验,在该基础上做了补充和删减,均链接到相应的地址(链接失效请留言评论). 一. ...

  8. Java面试(1)

    一.Java基础 什么是字符串常量池? Java中的字符串常量池(String Pool)是存储在Java堆内存中的字符串池: String是java中比较特殊的类,我们可以使用new运算符创建Str ...

  9. java各种面试问题

    二.Java多线程相关 线程池的原理,为什么要创建线程池?创建线程池的方式: 线程的生命周期,什么时候会出现僵死进程: 说说线程安全问题,什么实现线程安全,如何实现线程安全: 创建线程池有哪几个核心参 ...

随机推荐

  1. 转贴:110个Oracle 函数

    转载地址:https://bbs.csdn.net/topics/310021870 1. ASCII返回与指定的字符对应的十进制数;SQL> select ascii(A) A,ascii(a ...

  2. 深入理解xLua热更新原理

    热更新简介 热更新是指在不需要重新编译打包游戏的情况下,在线更新游戏中的一些非核心代码和资源,比如活动运营和打补丁.热更新分为资源热更新和代码热更新两种,代码热更新实际上也是把代码当成资源的一种热更新 ...

  3. Azure Storage 系列(五)通过Azure.Cosmos.Table 类库在.Net 上使用 Table Storage

    一,引言 上一篇文章我们在.NET 项目中添加了 “WindowsAzure.Storage” 的 NuGet 包进行操作Table 数据,但是使用的 “WindowsAzure.Storage”  ...

  4. sql注入 报错注入常用的三种函数

    1.floor()函数 报错原因是 报错的原因是因为rand()函数在查询的时候会执行一次,插入的时候还会执行一次.这就是整个语句报错的关键 前面说过floor(rand(0)*2) 前六位是0110 ...

  5. ulimit 的认识

    原文出自 通过 ulimit 改善系统性能 概述 系统性能一直是一个受关注的话题,如何通过最简单的设置来实现最有效的性能调优,如何在有限资源的条件下保证程序的运作,ulimit 是我们在处理这些问题时 ...

  6. STL-Deque(双端队列)与单调队列的实现

    前言: STl是个好东西,虽然他在不开O2的条件下会跑的很慢,但他着实会让你的代码可读性大大提高,令你的代码看起来既简单又整洁. 双端队列: 顾名思义,双端队列是有两个头的,一个队首指针,一个队尾指针 ...

  7. C语言知识汇编

    (20-) 1.局部变量:定义在大括号的变量是局部变量 作用域:从 定义变量到return或者遇到 } 结束为止 include <stdio.h> int main() { int nu ...

  8. 每日一道 LeetCode (48):最长回文子串

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

  9. 番外篇 - Linux环境准备

     这是一个比较早的系列,最近发现一直没有更新...    asp.net core跨平台,所以我们首先需要一个linux来验证,所以第一篇就是准备我们的环境   .netcore尝试在centos6. ...

  10. python库之argparse

    先运行一个干净的argparse 由于没有添加任何参数,所以只能用自带的 -h(--help)参数 现在来加一个参数 所以echo为必填项 描述在-h时会出现 type=int指定参数只能是数字,否则 ...