关于ThreadLoacl的探究(原理,使用场景,内存泄露问题)

聊一聊ThreadLocal内存泄漏的问题 ThreadLocal你真的懂了吗? 阅读详情

解决了什么问题

ThreadLoacl解决了同一线程内多方法共享实例的参数传递问题。也就是如果一个参数在此线程下多个方法中使用时,你可以显示的声明每个方法共用的参数,然后调用的时候进行传递。也可以放到ThreadLoacl中,这样就不用每个方法必须显示的定义共用参数了。因为是同一线程内,所以不涉及多线程的问题。而和多线程相关的就是每个线程有自己的实例,互相之间互不影响。

实现原理

看一下ThreadLoacl的源码能帮助我们更好的理解ThreadLoacl。
当你用ThreadLoacl保存一个线程共用数据时,查看源码发现是保存在了当前线程Thread的成员变量ThreadLocal.ThreadLocalMap threadLocals中。key是你的Threadlocal,value就是你要放的值。
由此可以了解到是如何实现每个线程使用自己的变量副本,是因为数据保存在线程的成员变量中,使用时每个线程使用自己成员变量中保存的数据。

//Threadloacl的set方法
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
//getMap(t); 返回的是线程的成员变量 Thread类内的 ThreadLocal.ThreadLocalMap threadLocals成员变量
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
//ThreadLocal.ThreadLocalMap 主要的内容是一个  Entry,关于map使用Entry保存数据的内容就不再赘述,这里我们需要注意一下 这个Entry继承自WeakReference(弱引用对象)
static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }

使用场景

既然ThreadLoacl解决了同一线程内多方法共享实例的参数传递问题,那么使用场景就是同一线程中你有一些变量需要在多方法中公用。例如

  1. SimpleDateFormat是线程不安全的,如果你在主线程中创建了这个对象,然后在多个子线程中使用,那么就会存在问题。你就可以放到ThreadLoacl中,这样保证每个线程有自己独立的副本,这样就避免SimpleDateFormat线程不安全的问题。
  2. Spring的@Transactional如何保证同一事物呢,就是使用ThreadLoacl,当你同一线程多个方法涉及到数据库操作时,使用的就是此线程ThreadLoacl中保存的数据库连接从而保证了事物的实现。

内存泄露问题

下面我么来聊一下ThreadLocal存在的内存泄露问题。
首先根据它的原理我们画一个图来帮助我们更加清楚的理解。
内容是 我们在线程创建了一个ThreadLocal对象,然后使用它的副本。
ThreadLoacl的内存使用图形
首先说我们使用完这个数据之后,不在使用时,
1我们通过把当前线程的ThreadLocal引用显示的赋值为null,以方便垃圾回收器在处理时,如果发现对内存中的ThreadLoacl对象没有引用指向时,回收它的内存。
这里我们注意到即便我们把当前线程的ThreadLocal引用显示的赋值为null,但是当前线程对象的ThreadlocalMap中的key依然引用了Threadlocal对象。这样的话我们以为ThreadLocal对象在我们把ThreadLocal引用显示的赋值为null后会被回收,其实却不是,就是因为线程对象的ThreadlocalMap中的key依然引用了Threadlocal对象,这样会造成内存泄漏。那么怎么解决这个问题呢,这里是用的ThreadlocalMap中的key继承WeakReference对象,而针对引用的强、软、弱、虚引用的不同,垃圾回收器的处理方式不同。如果这是一个弱引用,那么垃圾回收器会把引用的对象回收。这样就满足了我们把ThreadLocal引用显示的赋值为null后Threadlocal对象不会被回收的问题。
2当前线程没有结束,那么当Threadlocal对象被回收后,ThreadlocalMap中的value就访问不到了,但是它因为被ThreadlLoaclMap强引用所以依然不会被回收,那么仍然会产生内存泄露。不过Java为了最小化内存泄露的可能性和影响,在ThreadLocal的get、set的时候,都会检查当前key所指的对象是否为null,是则删除对应的value,让它能被GC回收。尽管这样,当我们不在使用这个key时就不会调用他的get和set方法。
所以正确的做法是我们不在使用这个Threadlocal时调用remove方法。

总结下来就是内存泄露涉及到Threadlocal对象的内存泄露和ThreadlocalMap中的value的内存泄露。
当一个线程为不停止的线程和执行时间长的线程时,尤为明显。
正确的做法是我们不在使用这个Threadlocal时调用remove方法。

FOC:【1】浅析SVPWM算法(七段式)以及MATLAB仿真验证 最近的科研项目需要使用到SVPWM算法,网上相关的原理介绍很多。对于纯应用的需求来说,或许有些内容上的冗余。 本文的目的就是简要并且明确的给出具体的计算步骤,可以帮助快速上手。同时利用MATLAB进行了简单算法验证。..................... 阅读详情

相关推荐

[学习笔记]Esp32 + 4G模块,随身wifi,ppp拨号上网

Esp32S3 + 4G模块制作随身WIFI教程

weixin_45595548的博客 7413

ThreadLocal原理、内存泄漏以及TransmittableThreadLocal说明

ThreadLocal原理、内存泄漏以及TransmittableThreadLocal说明

m0_47704296的博客 623

记录一下本地部署Dify的坑

1. 截止2025-3-4为止,请注意,不要直接拉Dify的1.0.0版本。请先试用0.15.3版本。1.0.0有一个bug需要解决。3. 请使用docker-ce 新版本,docker-engine等老版本可能会有部分容器启动脚本执行莫名报错。2. 注意,请使用docker-compose V2版本,或者V1较高版本,否则会导致解析官方yml模板错误。

哈利路亚的收藏夹 5346

ThreadLocalMap为什么要定义在ThreadLocal中,而不直接定义在Thread中?

刚看了一下ThreadLocal的源码,刚开始一直看不懂为什么ThreadLocalMap中要定义一个Entry。 最初的理解是只需要在ThreadLocalMap中定义一个Object类型的成员变量就可以了,直到看到网上看到有博主在手机上画的一幅草图才明白: 一个ThreadLocal对应一个线程,但是可没人说一个线程也只能有一个ThreadLocal。 发现ThreadLocalMap的作用是...

qq_36450673的博客 2292

AD9176 双通道高速DAC调试记录

AD9176是一款高性能双通道16位数模转换器,支持高达12.6GSPS采样率,专为多频段无线应用设计。该器件集成8通道15.4Gbps JESD204B接口,支持复数/实数数据输入,每通道最大输入速率达3.08GSPS。关键特性包括:48位高精度NCO、灵活的插值滤波器(最高12倍)、优异的动态性能(SFDR达-83dBc@1.84GHz)以及多芯片同步功能。硬件调试需重点关注时钟配置(建议250M基准时钟)、JESD参数匹配及交流耦合设计。测试指标要求SFDR>55dBc@312MHz,实测值可达65d

universaldata的博客 1489

LabVIEW面向对象编程:操作者框架入门实战

本文是LabVIEW面向对象编程中操作者框架的入门实战指南。针对传统“面条式代码”在复杂项目中的维护难题,文章通过创建操作者、定义消息与处理函数、在主VI中调用等步骤,详细演示了如何利用操作者框架构建模块化、易扩展的应用程序架构,有效管理并行任务。

f0g1h2的博客 589

ThreadLocal真会内存泄漏?

在讨论ThreadLocal存在内存泄漏问题之前,我觉得有必要先了解一下什么是内存泄漏?我们为什么要解决内存泄漏的问题?这里引用一段百度百科对内存泄漏的解释。内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。从Java的内存管理来说,就是ThreadLocal存在无法被GC回收的内存。

Gefangenes的博客 786

如何设置反馈点

前面的POWER DC仿真都是忽略反馈线进行的仿真,如果单板压降不过,电源会自动调整输出电压,来满足负载的得到额定的电压.可以看到因为设置了反馈点,源端电压就被抬高到满足压降的值了。仿真上也可以自己添加反馈点,以得到抬高后的电源输出电压值。同样以下图的CPU的Core电源为例。按照流程正常设置好参数。

weixin_54787054的博客 1147

ThreadLocal的内存泄露问题

在上述所说的问题中,即使ThreadLocalMap中存在key为null的Entry,但是该Entry的value值并不会因为GC而被回收(value存本身就存着一个强引用的对象),所以就导致了该对象不会被回收掉而出现了内存泄露。假设如果存储的强引用,我们断开ThreadLocal Reference —> ThreadLocal的引用,会发现key强引用了ThreadLocal,导致该对象永远无法被GC。学习的过程中想到了一个问题,弱引用会不会导致运行过程中GC清除key,导致找不到对应的value?

sunao1106的博客 4759

MATLAB代码实现了一个柱塞泵配流盘过流面积的计算和可视化功能

该MATLAB代码实现了一个柱塞泵配流盘过流面积的计算和可视化功能。输出曲线可直接用于验证设计的合理性(如是否存在过流面积突变或不足)。的不同范围,选择对应的几何模型计算过流面积。通过分段逻辑计算柱塞腔在不同旋转角度(过流面积在特定条件下会被限制(如。),确保结果符合物理实际。条件分支,根据旋转角度。

huanghm88的专栏 582

【ESP 保姆级教程】第三方库篇 ——TimeLib库,一个非常Nice的时间库,结合第三方进行校正时间

Time,这是一个为Arduino提供时间支持的库。 这个库的例子中会教会我们多种方式去获取时间: - 一个`RTC`时钟 - 网络`NTP`时间 - `GPS`时间

单片机菜鸟哥的博客 3674

ThreadLocal底层原理,内存泄露问题,以及如何在项目中使用这个关键字(总结)

通过实现线程本地存储,每个线程有独立的变量副本。使用不当会导致内存泄露,需及时调用remove()清理。在项目中常用于会话管理、数据库连接管理和日志跟踪等场景。

m0_73078350的博客 774

使用 syncstart 实现同场景下多个音视频音轨自动化同步

如果需要在视频编辑中同步多个机位的音轨,使得相同的视频能够同时播放,手动操作可能会变得相当复杂。特别是当处理多个视频文件时,例如有10个视频需要互相匹配,实现一对多的同步关系,这就涉及到为每对视频生成匹配的音轨数据。手动完成这样的任务,如生成90套对应的音轨数据,不仅耗时而且容易出错。因此,使用脚本自动化这一过程是一个更为高效和准确的解决方案。通过编写脚本,您可以批量处理多个视频文件,自动同步它们的音轨,大大简化了音视频编辑的工作流程,并确保了同步的准确性。

Mr数据杨 1076

ThreadLoacl

目录三. ThreadLoacl 基础二. InheritableThreadLocal三. TransmittableThreadLocal 三. ThreadLoacl 基础 在Java的多线程编程中,为保证多个线程对共享变量的安全访问,通常会使用synchronized来保证同一时刻只有一个线程对共享变量进行操作。 但在有些情况下,synchronized不能保证多线程对共享变量的正确读写。例如类有一个类变量,该类变量会被多个类方法读写,当多线程操作该类的实例对象时,如果线程对类变量有读取、写入操

qq_29799655的博客 223

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

ThreadLocal原理分析与使用场景

什么是ThreadLocal变量 ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意: 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来。 既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。 ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量

聆听。。花开雨落的博客 243

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

源码分析_ThreadLoacl源码分析

“今天我们一起探讨下ThreadLocal的实现原理和源码分析。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景。相信本文一定能让大家完全了解ThreadLocal。”01—ThreadLoacl是什么?? ThreadLocal是啥?面试的时候经常会被问到,有些人喜欢将他与线...

weixin_34438187的博客 97

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

ThreadLocal的底层原理

(3)如果在线程池中使用ThreadLocal会造成内存泄露,因为当ThreadLocal对象使用完之后,应该吧要设置的key,value,也就是Entry对象回收,但是线程池中的线程不会被回收,而线程对象是通过强引用指向ThreadLocalMap,ThreadLocalMap通过强引用指向Entry对象,线程不被回收,那么Entry对象也不会被回收,从而出现内存泄露,解决办法是在使用了ThreadLocal对象之后,手动调用ThreadLocal的remove方法,手动清楚对象。

weixin_49131718的博客 519

ThreadLocal探究

目录 一、ThreadLocal是什么 二、ThreadLocal怎么用 三、ThreadLocal源码分析 四、ThreadLocal其他几个注意的点 参考文章: 面试官没想到ThreadLocal我用得这么溜,人直接傻掉 再有人问你什么是ThreadLocal,就把这篇文章甩给他! ThreadLocal,你想了解的都在这里(进来瞧瞧不后悔) ThreadLocal理解及应用​​​​​​​ 一、ThreadLocal是什么 从名字我们就可以看到ThreadLocal叫做..

一蓑烟雨任平生 366

Java并发编程 II - 没有共享就没有伤害(ThreadLoacl)

卡个位置,还没开始写

鱼蛋的博客 255

ThreadLocal类 | 并发编程

对象生成时机由我们控制,重写方法来保存对象。对象生成时机不由我们控制,调用set()方法来保存对象。线程安全不加锁,效率高高效利用内存:相比于每一个线程任务都新建一个,使用可以节约内存(注意线程池在此处与的关联)。解决场景二的问题。

BASK2311的博客 200

浅聊一下ThreadLocal

3 个方法:set () 存、get () 取、remove () 删(重点!2 个场景:线程数据隔离(防并发)、跨函数传数据(解耦);1 个注意点:线程池场景一定要在 finally 里调用 remove (),避免内存泄露和脏数据。掌握这些,不管是开发还是面试,ThreadLocal 这块都没问题了~

m0_69052535的博客 2116

聊聊并发:(十八)ThreadLocal分析

前言 在前面的文章中,我们陆续对concurrent包中的常用类进行了依次介绍,涵盖范围包括各种锁、并发容器、队列,理解这些类的作用以及原理,可以帮助我们更好的应对并发场景下带来的挑战,如果您还对其中哪些类的实现不太熟悉,建议您阅读一下之前的文章。 本篇,我们来介绍一下ThreadLocal的作用及其原理,基于JDK1.8。 ThreadLocal介绍 ThreadLocal是线程内部的数据存储类...

wtopps的专栏 436

深入理解ThreadLocal

ThreadLocal 是什么?ThreadLocal是一个为每个线程创建单独变量副本的类。ThreadLocal主要解决的是让每一个线程绑定自己的值,自己用自己的,不跟别的线程争抢。该类提供了线程局部 (thread-local) 变量。通过使用get()和set()方法可以访问线程自己的、独立于初始化的变量副本。即通过ThreadLocal可以让指定的值实现线程隔离(线程之间不存在共享关系),从而避免了线程安全的问题。ThreadLocal 的常用API。

BASK2312的博客 386

ThreadLocal和引用关系

一、引用类型-强软弱虚 强引用:通常=表示的引用 软引用:SoftReference,在内存不足时,垃圾回收器才回收 弱引用:WeakReference,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。ThreadLocal中使用了弱引用 虚引用:最弱的一种引用,垃圾回收器直接回收,主要堆外内存管理场景。例如:通过虚引用关联一块堆外内存的对象,当虚引用对象被回收后,引用堆外内存还没有回收,因此需要通知(采用一个Queue方式)gc进行回收 二、ThreadLocal

程序员的世界 945

线程内部存储ThreadLocal

1、是什么? 并发访问共享变量的时候可以考虑加锁控制(synchornized、Lock锁、volatile+cas)这种方式对内存友好,不用额外的开辟线程内的存储空间,但是并发的时候要互斥访问对效率不太友好; 早在JDK1.2的就提供了ThreadLocal的线程内部存储机制来解决并发访问题。设计思想是在线程内部存储共享变量的副本,在线程存活的过程中可以随时随意场景中取到自己保存的变量副本。 2、怎么使用? import java.util.concurrent.TimeUnit; publi

TT_130616的博客 725

ThreadLocal怎么才能导致内存溢出

在早期的JDK版本中,ThreadLocal的内部结构是一个Map,其中每一个线程实例作为Key,线程在“线程本地变量”中绑定的值为Value(本地值)。早期版本中的Map结构,其拥有者为ThreadLocal实例,每一个ThreadLocal实例拥有一个Map实例。在JDK 8版本中,ThreadLocal的内部结构发生了演进,虽然还是使用了Map结构,但是Map结构的拥有者已经发生了变化,其拥有者为Thread(线程)实例,每一个Thread实例拥有一个Map实例。

u010002517的博客 228
上一篇: mysql多次查询得到的java对象物理地址相同(源码探究)
下一篇: 项目启动失败 关键字 JPLISAgent.c line: 844
隐者诡道
博客等级 码龄11年 13粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值