1.概述

转载:ThreadLocal 内存泄漏 代码演示 实例演示

首先看文章:ThreadLocal内存泄露原因分析

相关文章:

【高并发】ThreadLocal、InheritableThreadLocal

【Java】Java中ThreadLocal简介以及源码

2.案例

2.1 不使用ThreadLocal

下面这段程序创建了一个有5个线程的线程池。
每个线程致性都申请5M大小的堆空间。

public class MyThreadLocalOOM1 {public static final Integer SIZE = 500;static ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 1,TimeUnit.MINUTES, new LinkedBlockingDeque<>());static class LocalVariable {//总共有5Mprivate byte[] locla = new byte[1024 * 1024 * 5];}public static void main(String[] args) {try {for (int i = 0; i < SIZE; i++) {executor.execute(() -> {new LocalVariable();System.out.println("开始执行");});Thread.sleep(100);}} catch (InterruptedException e) {e.printStackTrace();}}
}

使用JDK自带的VisualVM来观察对内存占用情况,下图中锯齿状的蓝色区域是堆已经使用的空间大小,可以看到在0-70内,这是因为每个线程都会申请5M空间,过一小段时间后,就会触发一次youngGC, 内存就会释放。

在19:30:36处我手动触发了一次GC ,可以看到堆空间基本都释放。

说明LocalVariable全都释放,未发生内存泄漏。

2.2 使用ThreadLocal,但不remove

public class MyThreadLocalOOM2 {public static final Integer SIZE = 500;static ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 1,TimeUnit.MINUTES, new LinkedBlockingDeque<>());static class LocalVariable {//总共有5Mprivate byte[] locla = new byte[1024 * 1024 * 5];}static ThreadLocal<LocalVariable> local = new ThreadLocal<>();public static void main(String[] args) {try {for (int i = 0; i < SIZE; i++) {executor.execute(() -> {local.set(new LocalVariable());System.out.println("开始执行");});Thread.sleep(100);}            local = null;//这里设置为null,依旧会造成内存泄漏} catch (InterruptedException e) {e.printStackTrace();}}
}

上面代码中定义了static的ThreadLocal变量local, 但是当for循环致性完毕后,又将local设置为null。普通对象,此时就没有强引用了,当GC时就会被回收掉。

但是通过下面图可以看到,即使for循环结束后手动触发了GC,堆内存空间依旧占用约25MB空间,正好是线程池中5个线程的LocalVariable对象的空间和。

所以发生了内存泄漏。

发生内存泄漏的原因见 ThreadLocal内存泄露原因分析

2.3 使用Thread Local,且remove

public class MyThreadLocalOOM3 {public static final Integer SIZE = 500;static ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 1,TimeUnit.MINUTES, new LinkedBlockingDeque<>());static class LocalVariable {//总共有5Mprivate byte[] locla = new byte[1024 * 1024 * 5];}final static ThreadLocal<LocalVariable> local = new ThreadLocal<>();public static void main(String[] args) {try {for (int i = 0; i < SIZE; i++) {executor.execute(() -> {local.set(new LocalVariable());System.out.println("开始执行");local.remove();});Thread.sleep(100);}} catch (InterruptedException e) {e.printStackTrace();}}
}

上面代码中,线程致性完成后,都调用了local.remove()来将threadLocal内的对象删除。下图中可以看到在手动触发GC后,对内存全部释放,未发生内存泄漏。

2.4 单线程演示内存泄漏

public class MyThreadLocalOOM4 {public static final Integer SIZE = 500;static class LocalVariable {//总共有50Mprivate byte[] locla = new byte[1024 * 1024 * 50];}static ThreadLocal<LocalVariable> local = new ThreadLocal<>();static LocalVariable localVariable;public static void main(String[] args) throws InterruptedException {try {TimeUnit.SECONDS.sleep(2);localVariable = new LocalVariable();local.set(new LocalVariable());System.out.println("开始执行");Thread.sleep(100);local = null;localVariable = null;} catch (InterruptedException e) {e.printStackTrace();}while (true) {TimeUnit.SECONDS.sleep(1);}}
}

从结果中可以看到,localVariable的50MB空间释放了,但是ThreadLocal中存放的50MB空间没有释放。

3.引用

像下面代码,stu是再for外面定义的,线程内每次都使用这个stu对象,那么依旧会有线程安全问题,因为该stu对象还是多线程之间共享这个对象。

所以一定要再每个线程内new对象,避免多线程共享。
也可以自己实现MyThreadLocal,来手动复制对象,避免复用同一个对象

p

ublic class MyThreadLocal<T> extends ThreadLocal<T> {public void set(T value) {String s = JSONObject.toJSONString(value);super.set((T) JSONObject.parseObject(s, value.getClass()));}
}

【java】ThreadLocal 内存泄漏 代码演示 实例演示相关推荐

  1. 使用Java创建内存泄漏

    我刚刚接受采访,并被要求使用Java造成内存泄漏 . 不用说,我对如何开始创建它一无所知. 一个例子是什么? #1楼 最近,我遇到了一种更细微的资源泄漏. 我们通过类加载器的getResourceAs ...

  2. 内存泄漏代码_调查内存泄漏第1部分–编写泄漏代码

    内存泄漏代码 前几天,我发现了这个小问题:该服务器运行了一段时间,然后掉下来了. 然后通过启动脚本重新启动,整个过程重复进行. 听起来并没有什么坏处,因为它虽然对数据造成了重大损失,但对业务的重要性并 ...

  3. java static内存泄漏_Java中的内存泄漏

    内存泄漏是指不再使用的对象持续占有内存空间而得不到及时释放,从而造成内存空间的浪费称为内存泄漏.比如,长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄漏,尽管短生命周期对象已经不再需要,但是 ...

  4. Java 堆内存泄漏分析的一个例子

    Java 程序开发者,多多少少都遇到过 Java 堆内存溢出的错误,错误发生时可以在日志文件中看到 java.lang.OutOfMemoryError: Java heap space 字样.不像  ...

  5. 深入分析 ThreadLocal 内存泄漏问题

    转载自 http://www.importnew.com/22039.html ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件 ...

  6. java程序内存泄漏场景及预防

    为什么80%的码农都做不了架构师?>>>    虽然jvm有垃圾回收机制,如果程序编写不注意某些特定规则,仍然会导致java程序内存泄漏,最终可能出现OutOfMemory异常. 1 ...

  7. 【转载】深入分析 ThreadLocal 内存泄漏问题

    前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用 ThreadLocal,就可 ...

  8. 聊一聊ThreadLocal内存泄漏的问题

    回答任何一个问题的时候应该要遵循:明确题意-->深入浅出-->举例说明-->总结,这四个步骤很重要,可以让你沉着冷静,思路清晰,避免尴尬. 01 -  明确题意 明确题意的意思就是先 ...

  9. ThreadLocal内存泄漏原理解析

    1.什么是内存泄漏问题? 内存泄漏 表示就是我们申请了内存,但是该内存一直无法释放: 内存泄漏会导致内存溢出问题: 申请内存时,发现申请内存不足,就会报错 : 2.在介绍ThreadLocal内存泄漏 ...

最新文章

  1. 李航统计学习方法视频教程
  2. ubuntu 安装deb_Ubuntu不完全小坑指南
  3. 阿里巴巴在应用性能测试场景设计和实现上的实践
  4. gitblit mysql_CentOS7安装MySQL、Tomcat和GitBlit记录
  5. leetcode 376. Wiggle Subsequence | 376. 摆动序列(动态规划)
  6. 搞不懂,为啥现在什么公司都在考算法???
  7. SpringSecurity自动登录详解
  8. c语言如何找一个数的ac码,详细解析C语言中的开方实现
  9. 谷歌浏览器老是出现花_Google全新的AI平台值得您花时间吗?
  10. mysql查询前一年的第一天_MySQL中查询某一天, 某一月, 某一年的数据代码详解
  11. 哪里的http和socks5代理ip稳定速度快
  12. sony android 计算器,NeoCal 全能计算器 V2.0.2
  13. sleuth zipkin reporter-sender 分析
  14. 【VMware】虚拟机中映射USB设备
  15. MMC、SD、TF、SDIO、SDMMC简介
  16. 在家远程控制公司电脑怎么实现 7款好用的远程工具介绍
  17. abb机器人码垛编程详解_ABB机器人码垛程序
  18. Linux系统概念复习
  19. STM32L431(CubeMX)使用DHT11读取环境温度与湿度并通过串口打印
  20. (转)e-config Proposed List 中的 5313-HPO IBM Power Software HIPO 条目是什么

热门文章

  1. 中国电信与中国联通启动2.1GHz 5G主设备集采,规模24万站
  2. 散户“大溃败”?GME连续5日暴跌80% 白银价格急转直下
  3. 性价比还是小米狠:两场下来友商完败?
  4. “你出命,我出钱!”靠玩命,他又做了一次首富
  5. 惊现“鬼影”!iPhone 11系列夜景拍照频频翻车
  6. 微信内测新功能:公众号们脖子一凉...
  7. 斗鱼上市首日低开平收 总市值37.3亿美元
  8. 善用AI技术,旷视发布《人工智能应用准则》
  9. 宁德时代811电芯初现真容 搭配宝马X1混动汽车能量密度提升近6成
  10. 特斯拉明年会有100万辆自动驾驶出租车 你敢坐吗?