Java面试题:细数ThreadLocal大坑,内存泄露本可避免
一、背景
ThreadLocal是Java中用于解决多线程共享变量导致的线程安全问题的一种机制。它为每个线程分配一个独立的变量副本,从而避免了线程间的数据竞争。这个我们从上一篇文章《Java面试题:请谈谈对ThreadLocal的理解?》中已经了解。然而,如果使用不当,ThreadLocal也可能导致内存泄露。
那什么是内存泄漏,它和内存溢出有什么区别?
内存溢出(Memory overflow):没有足够的内存提供申请者使用。
内存泄漏(Memory leak):指程序申请内存后,无法释放已申请的内存空间,内存泄漏的堆积终将导致内存溢出。
二、内存泄露案例
以下是一个可能导致ThreadLocal内存泄露的代码示例:
public class ThreadLocalMemoryTest {
// 定义一个静态的ThreadLocal变量
private static final ThreadLocal<LeakyObject> threadLocal = new ThreadLocal<>(); public static void main(String[] args) {
// 创建一个对象并且存储到ThreadLocal中
threadLocal.set(new LeakyObject()); // 强制进行垃圾回收,以便我们可以看到对象是否被回收
System.gc(); try {
// 等待垃圾回收器进行垃圾回收
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} // 打印MemoryLeakyObject是否被回收的信息
if (LeakyObject.isInstanceActive()) {
System.out.println("LeakyObject instance is still active!");
} else {
System.out.println("LeakyObject instance has been garbage collected.");
} while(true) { }
} // 一个简单的内存泄漏示例类
private static class LeakyObject {
private static boolean instanceActive = true; @Override
protected void finalize() throws Throwable {
super.finalize();
instanceActive = false;
System.out.println("LeakyObject finalize method has been called.");
} public static boolean isInstanceActive() {
return instanceActive;
}
}
}
运行结果如下:
LeakyObject instance is still active!
在这个例子中,我们定义了一个LeakyObject类,它有一个静态变量instanceActive来跟踪对象实例是否仍然存在。重写的finalize方法会在对象被垃圾回收器回收时被调用,并将instanceActive设置为false。
三、代码优化与内存泄露避免
为了解决这个问题,我们需要确保在不再需要ThreadLocal中的数据时释放其占用的内存,从而避免内存泄露。在System.gc();代码执行之前,模拟清除ThreadLocal中的数据。
// 模拟线程退出,应该清除ThreadLocal中的数据
threadLocal.remove();
// 强制进行垃圾回收,以便我们可以看到对象是否被回收
System.gc();
运行结果如下:
LeakyObject finalize method has been called.
LeakyObject instance has been garbage collected.
ThreadLocalMemoryLeakTest类中的main方法模拟了ThreadLocal的使用,并在使用后调用remove方法来清除ThreadLocal中的数据,然后强制进行垃圾回收并等待一段时间,最后检查对象是否被垃圾回收器回收。
四、总结
ThreadLocal作为一种解决多线程共享变量问题的机制,在正确使用的情况下可以提供很高的性能和可靠性。然而,如果不正确使用,它也可能导致内存泄露。
通过了解并避免上述案例中的问题,我们可以更好地利用ThreadLocal来提高应用程序的性能和可靠性。在本次案例中,我们是通过ThreadLocal.remove()方法,来解决内存泄漏问题。
但是其实解决ThreadLocal内存泄漏问题的方法还有2种,需要依据不同的使用场景:
- 使用不可变对象:ThreadLocal变量存储的对象最好是不可变的,因为不可变的对象不需要频繁更新,也不会因为被多个线程同时修改而出现线程安全问题。如果要修改一个ThreadLocal变量中的对象,最好使用一个新的对象替换原有的对象,从而避免引用泄漏的问题。
- 使用弱引用:ThreadLocalMap中的弱引用可以保证ThreadLocal实例在当前线程中不再被引用时能够被GC回收,从而防止内存泄漏问题的发生。
Java面试题:细数ThreadLocal大坑,内存泄露本可避免的更多相关文章
- ThreadLocal的内存泄露(转)
ThreadLocal的目的就是为每一个使用ThreadLocal的线程都提供一个值,让该值和使用它的线程绑定,当然每一个线程都可以独立地改变它绑定的值.如果需要隔离多个线程之间的共享冲突,可以使用T ...
- ThreadLocal的内存泄露
ThreadLocal的目的就是为每一个使用ThreadLocal的线程都提供一个值,让该值和使用它的线程绑定,当然每一个线程都可以独立地改变它绑定的值.如果需要隔离多个线程之间的共享冲突,可以使用T ...
- Java技术专题之JVM你的内存泄露了吗?
一.从一个例子开始 关于JVM的内存泄露,让我们从下面一个例子开始吧,大家来判断一下如果按照下面这种分配方式,会不会出现内存泄露呢? import java.util.List; import jav ...
- Java有了GC同样会出现内存泄露问题
1.静态集合类像HashMap.Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象Object也不能被释放,因为他们也将一直被Vector等应用着. Static ...
- java程序——CPU过高100%及内存泄露排查
CPU过高 这类问题可以使用 top 命令观察一些,CPU 是不是都被 Java 程序占用了.比如下面这个截图: 服务器的 CPU 大多都被 Java 占用了.这正是我们之前生产上 CPU 过高的一个 ...
- 2019 Java面试题
马上又是一个金九银十的招聘旺季,小编在这里给大家整理了一套各大互联网公司面试都喜欢问的一些问题或者一些出场率很高的Java面试题,给在校招或者社招路上的你一臂之力. 首先我们需要明白一个事实,招聘的一 ...
- java面试题(目录版)
在https://www.cnblogs.com/marsitman/p/9539369.html 根据自己以往的面试经验,在该基础上做了补充和删减,均链接到相应的地址(链接失效请留言评论). 一. ...
- Java 程序的内存泄露问题分析
什么是内存泄露? 广义的Memory Leak:应用占用了内存,但是不再使用(包括不能使用)该部分内存 狭义的Memory Leak:应用分配了内存,但是不能再获取该部分内存的引用(对于Java,也不 ...
- ThreadLocal以及内存泄漏
ThreadLocal是什么 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用Thr ...
- Java读源码之ThreadLocal
前言 JDK版本: 1.8 之前在看Thread源码时候看到这么一个属性 ThreadLocal.ThreadLocalMap threadLocals = null; ThreadLocal实现的是 ...
随机推荐
- setting.json 20210825 更新
vue代码格式化思路 { "pasteImage.path": "${currentFileNameWithoutExt}_Images/", "up ...
- git clone error: RPC failed; curl 18 transfer closed with outstanding read data remaining
备忘 git clone比较大的工程时,出现这种错误:error: RPC failed; curl 18 transfer closed with outstanding read data rem ...
- 流媒体通信中RTP/RTCP在项目中的应用
一 概述: 本文档描述RTC通信中RTP/RTCP的应用以及当前项目中的使用策略. 二 RTP/RTCP协议简介 2.1 协议标准 RTP 由 IETF(http://www.ietf.org/)定义 ...
- RTMP、X264与交叉编译
RTMP.X264与交叉编译 与HTTP(超文本传输协议)同样是一个基于TCP的Real Time Messaging Protocol(实时消息传输协议).由Adobe Systems公司为Fl ...
- 从null-ls归档再看nvim的代码格式化与lint方案
由于null-lsp的归档和暂停更新,我们需要重新审视并思考还有哪些架构简单易于理解的插件配置方案.本文将介绍脱离null-ls插件体系下的代码格式化和lint的插件配置方案. 在之前的文章中< ...
- 3D渲染慢,直接买显卡还是用云渲染更划算?
3D渲染对建筑师和设计师来说并不陌生,3D渲染的过程中出现渲染卡顿.特殊材质难以渲染,或者本地配置不足.本地渲染资源不够时,常常会影响工作效率.本文比较了3D渲染时,为提高工作效率,买显卡还是用云渲染 ...
- 让艺术触手可及!3DCAT实时云渲染赋能真浪数字艺术馆首展
2023年5月18日,由真浪数字艺术和EZVR联合打造的真浪数字艺术馆首展–「破界·交织」让艺术更自由,正式与大家相见.此次展览分为五个主题展馆,汇聚了来自全球各领域的19位青年数字艺术家一同探讨虚实 ...
- 记录--实现一个鼠标框选的功能,要怎么实现和设计 api?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 前两年在一家做电商的公司做了一个需求:鼠标框选商品卡片,开始拖拽的时候合成一个然后改变位置,页面上有几千个所以还要结合虚拟列表.当时 ...
- [.NET项目实战] Elsa开源工作流组件应用(三):实战演练
补充 之前的文章简单介绍了工作流和Elsa工作流库,这里再补充说明两点 工作流的使用场景非常广泛,几乎涵盖了所有需要进行业务流程自动化管理的领域. 学习一个开源库,最简单的方法就是看源码,Elsa的工 ...
- 【面试】将 95% 求职者拒之门外的BAT大数据面试题-附解题方法(文末有福利)
写在前面 最近不少读者找我要大数据面试题,我整理了很久,筛选出这10道容易出错的大数据面试题,希望对大家有所帮助.题目与解答整理自互联网,感谢分享这些面经的技术大牛们! 题目概览 如何从大量的 URL ...