ThreadLocal 内存泄漏问题
1. 认识ThreadLocal
java中提高了threadlocal,为每个线程保存其独有的变量,threadlocal使用的一个小例子是:
public class ThreadLocalTest {public static void main(String[] args) {ThreadLocal<String> threadIds = new ThreadLocal<>();ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);for (int i = 0; i < 10; i++) {fixedThreadPool.execute(() -> {threadIds.set("" + Thread.currentThread().getId());System.out.println(Thread.currentThread().getName() + ", id:" + threadIds.get());});}}
}
输出结果:
Thread-0, id:12
Thread-3, id:15
Thread-2, id:14
Thread-5, id:17
Thread-1, id:13
Thread-6, id:18
Thread-4, id:16
Thread-7, id:19
Thread-9, id:21
Thread-8, id:20
可以看出,每个线程内部都保存了一个不同的threadId。
2. ThreadLocal实现原理
每个线程(Thread类的实例)都具有一个叫做threadLocalMap的变量,其是一个map类型的结构,其中每个key指向一个threadLocal实例,value存储当前线程在这个threadLocal中存储的值。举例来说,在上面的程序中我们创建了10个线程,每个线程内部的threadLocalMap都具有一个entry<threadIds, v>。因此,每个线程记录、更改threadLocal中的值实际上就是在自己的threadLocalMap中找到对应的entry,然后更新entry里面的值,从而实现线程隔离。
3. ThreadLocalMap中的key是软引用
我们知道,ThreadLocalMap中的key是对ThreadLocal的引用,那为什么搞成软引用呢,我的理解是这样的。

图片来自于zhihu java喵
看上图,实线代表强引用,虚线代表弱引用。
我们结合上面的代码来理解一下:
首先,我们需要知道线程的寿命是很长的,我们在线程池中创建的线程之后可能还会去运行其他的runnable对象,因此需要动态地清理其threadLocalMap中无用的entry。
- 当main方法被执行时,main方法被压入虚拟机栈,创建了10个线程,假设线程还没终止,那么此时threadIds对象具有1个强引用(来自于main线程的ThreadLocal threadIds = new ThreadLocal<>();这句)和10个弱引用(来自于10个线程的threadLocalMap中的key)。
- 当main方法运行之后,main方法被弹出栈,此时threadIds对象只具有10个弱引用(来自于10个线程的threadLocalMap中的key)。
- java gc线程发现threadIds对象只有弱引用,那么在gc时就会回收这个对象,之后每个线程的threadLocalMap中这个entry的key就变成了null。(此时entry是<null, v>)。
- 由于此时这条entry已经无用的,但是v还指向其引用的对象,那么v就无法被回收,造成了内存泄漏。
- 我刚看到这个问题时,想着解决办法也很简单,线程发现key是null之后,将v也置为null,等着gc回收v不久好了吗,实际上也确实可以这么做。
Q:为什么ThreadLocalMap的key是弱引用?
A:结合上面的流程就很简单了,如果key是弱引用,那么main方法都运行完了,threadIds都已经无用了,此时还有十个强引用指向它,这让gc怎么回收呢?
4. 内存泄漏解决方法
使用完threadLocal对象之后,调用remove方法,将其从线程的threadLocalMap中清理出去:
public class ThreadLocalTest {public static void main(String[] args) {ThreadLocal<String> threadIds = new ThreadLocal<>();ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);for (int i = 0; i < 10; i++) {fixedThreadPool.execute(() -> {threadIds.set("" + Thread.currentThread().getId());System.out.println(Thread.currentThread().getName() + ", id:" + threadIds.get());// removethreadIds.remove();});}}
}
相关文章:
ThreadLocal 内存泄漏问题
1. 认识ThreadLocal java中提高了threadlocal,为每个线程保存其独有的变量,threadlocal使用的一个小例子是: public class ThreadLocalTest {public static void main(String[] args) {ThreadLocal<String> threadIds new ThreadLoc…...
【算法】两道算法题根据提供字母解决解码方法和城市的天际线天际线问题
算法目录解码方法Java解答参考:天际线问题Java解答参考:大家好,我是小冷。 上一篇了解了项目相关的知识点 接下来看下两道算法题吧,用Java解答,可能更能激发一下大脑思考。 解码方法 题目要求: 一条包含…...
Python-TCP网络编程基础以及客户端程序开发
文章目录一. 网络编程基础- 什么是IP地址?- 什么是端口和端口号?- TCP介绍- socket介绍二. TCP客户端程序开发三. 扩展一. 网络编程基础 - 什么是IP地址? IP地址就是标识网络中设备的一个地址 IP地址分为 IPv4 和 IPv6 IPv4使用十进制, IPv6使用十六进制 查看本机IP地址: l…...
超低成本DDoS攻击来袭,看WAF如何绝地防护
一、DDoS攻击,不止于网络传输层 网络世界里为人们所熟知的DDoS攻击,多数是通过对带宽或网络计算资源的持续、大量消耗,最终导致目标网络与业务的瘫痪;这类DDOS攻击, 工作在OSI模型的网络层与传输层,利用协…...
CF1795E Explosions? (单调栈)
传送门 题意: 有 n 个怪兽需要消灭,它们的生命值分别是 h [1],h [2]......h [n]. 我们可以使用两种技能: 技能 1:选择任意一个怪兽,使其生命值降低 1 点,并且需要 1 点能量值. 技能 2:选择任意…...
C++——二叉树排序树
文章目录1 二叉搜索树概念2 二叉搜索树操作与模拟实现2.1 二叉搜索树的查找非递归版本递归版本2.2 二叉搜索树的插入非递归版本递归版本2.3 二叉搜索树的删除非递归版本递归版本3 二叉搜索树的应用(K模型、KV模型)4 二叉搜索树的性能分析1 二叉搜索树概念…...
深拷贝浅拷贝的区别?如何实现一个深拷贝?
一、数据类型存储 JavaScript中存在两大数据类型: 基本类型 Number String null Undefined Boolean symbol引用类型 array object function 基本类型数据保存在在栈内存中 引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的…...
Linux应用编程下连接本地数据库进行增删改查系列操作
文章目录前言一、常用SQL操作语句二、相关函数解析三、连接本地数据库四、编译运行五、程序源码前言 本篇为C语言应用编程下连接Linux本地数据库进行增删改查系列操作。 在此之前,首先当然是你需要具备一定的数据库基础,所以下面我先列出部分常用的SQL…...
图论学习03
图神经网络模型介绍 将图神经网络分为基于谱域上的模型和基于空域上的模型,并按照发展顺序详解每个类别中的重要模型。 基于谱域的图神经网络 谱域上的图卷积在图学习迈向深度学习的发展历程上起到了关键性的作用。三个具有代表性的谱域图神经网络 谱图卷积网络切…...
解决qt中cmake单独存放 .ui, .cpp, .h文件
设想 项目文件较多,全部放在一个目录下就像依托答辩。 希望能将头文件放入include,ui文件放入ui,源文件放入src。 为了将Qt代码和一般非Qt代码分离开,进一步地: 将Qt源文件放入qt_src,普通源文件放入sr…...
操作系统(day12)-- 基本分段存储,段页式存储
基本分段存储管理方式 不会产生内部碎片,会产生外部碎片 分段 按照程序自身的逻辑关系划分为 若干个段,每个段都有一个段名,每段从0开始编址 分段存储管理方式中一个段表项由段号(隐含)、段长、基地址 分段的段表项固…...
疯狂弹出请插入多卷集的最后一张磁盘窗口
整个人嘛了,今天插上U盘,跟tmd中了病毒一样, 屏幕疯狂弹出窗口, 提示请插入多卷集的最后一张磁盘! 点确定之后他继续弹出,点取消它也继续弹出, 关掉一个又弹出来一个,妈的&#x…...
Spark12: SparkSQL入门
一、SparkSQL Spark SQL和我们之前讲Hive的时候说的hive on spark是不一样的。hive on spark是表示把底层的mapreduce引擎替换为spark引擎。而Spark SQL是Spark自己实现的一套SQL处理引擎。Spark SQL是Spark中的一个模块,主要用于进行结构化数据的处理。它提供的最核…...
show profile和trance分析SQL
目录 一.show profile分析SQL 二.trance分析优化器执行计划 一.show profile分析SQL Mysql从5.0.37版本开始增加了对show profiles和show profile语句的支持。show profiles能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。。 通过have_profiling参数,能够…...
[AI生成图片] 效果最好的Midjourney 的介绍和使用
Midjourney介绍: 是一个文本生成图片的扩散模型,能够根据输入的任何文本生成令人难以置信的图像,让数十亿人在几秒钟内创造惊人的艺术。为方便用户控制和快速生成图片,打开后在页面底部输入文本内容,稍等一小会&#…...
Vue.use( ) 的核心原理
首先来思考几个问题: Vue.use是什么? vue.use() 是vue提供的一个静态方法,主要是为了注册插件,增加vue的功能。 Vue.use( plugin ) plugin只能是Object 或 Function vue.use()做了什么工作? 该js如果是对象 该对象…...
idea同时编辑多行-winmac都支持
1背景介绍 idea编辑器非常强大,其中一个功能非常优秀,很多程序员也非常喜欢用。这个功能能够大大大提高工作效率-------------多行代码同时编辑 2win 2.1方法1 按住alt鼠标左键上/下拖动即可 这样选中多行后,可以直接多行编辑。 优点&a…...
亿级高并发电商项目-- 实战篇 --万达商城项目 十一(编写商品搜索功能、操作商品同步到ES、安装RabbitMQ与Erlang,配置监听队列与消息队列)
👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 Ǵ…...
数据结构概述和稀疏数组
数据结构和算法内容介绍 1)算法是程序的灵魂,优秀的程序可以在海量数据计算时,仍然保持高速计算 数据结构和算法概述 1)程序 数据结构算法 2)学好数据结构可以编写出更加漂亮,更加有效率的代码 3&…...
宝塔搭建实战人才求职管理系统adminm前端vue源码(三)
大家好啊,我是测评君,欢迎来到web测评。 上一期给大家分享骑士cms后台admin前端vue在本地运行打包、宝塔发布部署的方式,本期给大家分享,后台adminm移动端后台vue前端怎么在本地运行,打包,实现线上功能更新…...
车载项目氛围灯功能——音乐律动
车载项目里面很多用到音乐律动,就是根据音乐的响度和频率,对应氛围灯的亮度和颜色,让人看起来跟着音乐在闪动。本文记录了从FWK的傅里叶函数获取响度和频率的方法,封装了一下工具类,留着以后使用package com.demo.func…...
C盘空间管理完全指南:从清理到预防,根治飘红
你的C盘是否在不知不觉中已经飘红?在清理文件的路上,你是否曾因误删系统文件而追悔莫及? C盘告急的普遍困境 每当Windows系统运行缓慢,或安装新软件时弹出磁盘空间不足的提示,用户的第一反应往往是查看C盘使用情况。…...
应用安全从被动到主动:企业如何提升弹性与可靠性,降低安全债务?
ZDNET核心观点应用安全需董事会层面问责,企业文化影响“设计即安全”工作,运营模式将预防转化为行动。企业聚焦软件策略改变网络安全结果,挑战是在开发周期早期融入安全措施,构建捕捉漏洞和隐患的工具技术。本文将从被动到主动的转…...
Nitric本地开发环境搭建:快速测试和调试的完整流程
Nitric本地开发环境搭建:快速测试和调试的完整流程 【免费下载链接】nitric Nitric is a multi-language framework for cloud applications with infrastructure from code. 项目地址: https://gitcode.com/gh_mirrors/ni/nitric Nitric是一个多语言框架&am…...
OpenClaw本地控制台:一站式图形化管理AI助手工作流
1. 项目概述:一个为本地OpenClaw工作流量身打造的控制台如果你和我一样,在Windows上折腾过OpenClaw,那你肯定经历过这种“精神分裂”式的管理体验:想启动服务,得切到终端敲命令;要改个模型配置,…...
专业级macOS歌词同步方案:LyricsX核心功能深度解析
专业级macOS歌词同步方案:LyricsX核心功能深度解析 【免费下载链接】LyricsX 🎶 Ultimate lyrics app for macOS. 项目地址: https://gitcode.com/gh_mirrors/ly/LyricsX LyricsX是一款专为macOS设计的专业级歌词同步工具,通过智能歌词…...
英雄联盟R3nzSkin换肤工具:5分钟快速上手免费皮肤解锁指南
英雄联盟R3nzSkin换肤工具:5分钟快速上手免费皮肤解锁指南 【免费下载链接】R3nzSkin-For-China-Server Skin changer for League of Legends (LOL) 项目地址: https://gitcode.com/gh_mirrors/r3/R3nzSkin-For-China-Server 还在为英雄联盟国服昂贵的皮肤价…...
离散数学“黑话”指南:命题、谓词、群论,一次讲清程序员常遇到的术语
离散数学“黑话”指南:程序员视角下的概念破译 刚接触算法优化时,我盯着论文里的"幺半群"概念发愣——这和我在代码里写的if-else有什么关系?直到某天用状态机处理用户权限时突然顿悟:原来离散数学的抽象术语࿰…...
UWB-IMU、UWB定位对比研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Anthropic新模型Mythos号称擅查漏洞,扫描curl代码却仅确认1个低危问题
Mythos高调亮相,扫描结果却令人意外 近期,Anthropic推出的AI安全分析模型Mythos引发广泛关注,该公司宣称其在发现源代码安全漏洞方面表现出色,甚至因此暂缓公开发布。然而,当Mythos扫描全球最广泛使用的开源命令行HTTP…...
