ThreadLocal了解

news2024/11/29 0:54:27

文章目录

    • 概述
    • 源码
    • 原理
    • 内存泄露
    • 应用场景

概述

  • ThreadLocal提供线程的局部变量,这种变量与普通变量的区别在于,每个访问这种变量的线程都有自己的、独立的变量副本。用于解决多线程间的数据隔离问题。

源码

//返回Thread实例的成员变量threadLocals
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

ThreadLocals 依赖于附加到每个线程的每线程线性探测哈希映射(Thread.threadLocals 和 inheritableThreadLocals)。ThreadLocal 对象充当键,通过 threadLocalHashCode 进行搜索。这是一个自定义哈希代码(仅在 ThreadLocalMap 中有用),它消除了相同线程使用连续构造的 ThreadLocals 的常见情况下的冲突,同时在不太常见的情况下保持良好的行为。

get方法

返回此线程局部变量的当前线程副本中的值。如果变量没有当前线程的值,则首先将其初始化为调用该方法返回 initialValue 的值。

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

set方法

将此线程局部变量的当前线程副本设置为指定值。大多数子类不需要重写此方法,仅依靠该方法 initialValue 来设置线程局部变量的值。

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

remove方法

删除此线程局部变量的当前线程值。如果此线程局部变量随后由当前线程 读取 ,则其值将通过调用其方法重新初始化,除非其 initialValue 值在此期间由当前线程 设置 。这可能会导致在当前线程中多次调用 initialValue 该方法。

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}

原理

在这里插入图片描述

多线程隔离

  • ThreadLocal提供线程局部变量。这些变量与普通对应变量的不同之处在于,访问一个变量的每个线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是希望将状态与线程(例如,用户 ID 或事务 ID)相关联的类中的私有静态字段。
  • 只要线程处于活动状态并且 ThreadLocal 实例可访问,每个线程都包含对其线程局部变量副本的隐式引用;线程消失后,其线程本地实例的所有副本都将受到垃圾回收(除非存在对这些副本的其他引用)。

ThreadLocalMap

  • ThreadLocalMap 是一个自定义的哈希映射,仅适用于维护线程本地值。不会在 ThreadLocal 类外部导出任何操作。该类是包私有的,允许在类 Thread 中声明字段。为了帮助处理非常大且长期存在的用法,哈希表条目对键使用 WeakReferences。但是,由于不使用引用队列,因此仅当表开始空间不足时,才能保证删除过时的条目。

内存泄露

  • ThreadLocalMap中的key是弱引用,而value是强引用。所以,如果ThreadLocal没有被外部强引用的情况下,在垃圾回收时,key会被清空掉,而value不会。ThreadLocal中就会出现key为null的Entry。假如我们不采取措施,value永远不会被GC回收,这个时候就可能会产生内存泄漏问题。
  • 解决办法:使用完ThreadLocal后,执行remove操作,避免出现内存溢出情况。

为什么key使用弱引用?

  • 如果使用强引用,当ThreadLocal 对象的引用(强引用)被回收了,ThreadLocalMap本身依然还持有ThreadLocal的强引用,如果没有手动删除这个key ,则ThreadLocal不会被回收,所以只要当前线程不消亡,ThreadLocalMap引用的那些对象就不会被回收, 可以认为这导致Entry内存泄漏。

强引用:普通的引用,强引用指向的对象不会被回收;
软引用:仅有软引用指向的对象,只有发生gc且内存不足,才会被回收;
弱引用:仅有弱引用指向的对象,只要发生gc就会被回收。

应用场景

  • 数据库事务:通过AOP的方式,对执行数据库事务的函数进行拦截。函数开始前,获取connection开启事务并存储在ThreadLocal中,任何用到connection的地方,从ThreadLocal中获取。函数执行完毕,提交事务释放connection。
  • 用户登录信息:用户登录信息好多个方法上都要用到,给每个方法都添加一个User非常麻烦,而且有些时候,如果调用链有无法修改源码的第三方库,User对象就传不进去了。而ThreadLocal可以在一个线程中传递同一个对象。
  • RequestContextHolder:Spring 提供的一个用来暴露 Request 对象的工具,利用 RequestContextHolder,可以在一个请求线程中获取到 Request,避免了 Request 从头传到尾的情况。一般项目中,会对这个类再次进行封装,便于获取请求的相关的信息,常见的比如用户信息。

总结起来使用的场景就是一下这些地方:

在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
线程间数据隔离
进行事务操作,用于存储线程事务信息。
数据库连接,Session会话管理。

你知道的越多,你不知道的越多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/646480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytest教程__测试用例的执行方式(2)

在pytest框架中,编写测试用例有如下约束: 所有的测试用例文件名都需要满足test_*.py格式或*_test.py格式。在测试用例文件中,测试类以Test开头,并且不能带有__init__方法,否则pytest不会执行该class。在测用例的class…

企业如何选择最佳的CDN服务?

根据研究表明,47%的客户更喜欢能在2秒内加载完成的网页,不仅如此,如果一个网站的加载时间超过3秒,那么40%的访问者会毫不犹豫的离开你的网站。所以使用正确的内容交付网络对初创公司尤为关键。它有助于实现快速、安全的内容交付。…

10_python——模块

目录 模块的概述 自定义模块 Python中的包 以主程序的形式执行 引用其他模块 模块的概述 什么是模块:在python中模块就是python程序,一个模块就是一个*.py的文件,通常情况下把能够实现某一特定功能的代码放置在一个文件中作为一个模块&…

前后端分离,就浅浅的看看

目录 前言 一、优点 二、跨域 1、概念 2、解决跨域 三、CORS 总结 前言 前后端分离是Web应⽤的⼀种前后端解耦的架构模式,‘前后端分离‘’,“前”,就是客户端,“后”就是服务器端,专门处理数据和业务逻辑&…

某网站cookie反爬记录

一、背景 最近做城投项目时候遇到一个问题,就是一个代码写好不动,我只操作页面,运行出来的结果却是页面上显示的内容。这就导致了我不能按自己的需求抓取指定模块的内容 二、示例 import requestsheaders {"Accept": "app…

蓝牙智能指纹锁解决方案OM6621PW

目前市面上蓝牙智能指纹锁一般采用MCU指纹传感器蓝牙芯片的方案,该方案采用MCU运行指纹识别算法,采用蓝牙作为数据交互,方案成本较高。 ONMICRO的单芯片蓝牙智能指纹锁解决方案OM6621PW,凭借其卓越的性能和创新的技术,…

Spring的存储与获取Bean

Spring的存储与获取Bean 🔎Spring—存储Bean配置扫描路径利用类注解进行存储添加注解存储Bean关于Id为什么需要五个类注解类注解之间的关系 利用方法注解进行存储关于Id 🔎Spring—获取Bean属性注入Set注入构造方法注入总结(Spring的注入方式? 它们之间…

FTL没有映射,跟发工资没有钱有什么区别

大家好,我是五月。 前言 FTL(Flash Translation Layer),即闪存转换层,是各种存储设备的核心算法,作用是将Host传下来的逻辑地址转换成物理地址,也就是映射。 地址映射是FTL最原始最基本的功能…

Pytest教程__简介与安装(1)

一、Pytest简介 pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但更灵活。 官方网站优点简介: 非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考能够支持简单的单元测试…

【Qt】Ubuntu安装GCC9.3.0版本的Qt5.15.5

目录 一、安装GCC9.3.0 1.下载GCC9.3.0源码 2.获取依赖项的包 3.生成Makefile文件 4.编译并安装 5.生成软链接 6. 查看GCC版本 二、安装Qt 1.下载Qt安装包 2.创建Qt项目并运行 一、安装GCC9.3.0 1.下载GCC9.3.0源码 https://ftp.gnu.org/gnu/gcc/gcc-9.3.0/gcc-9.3…

药物靶点信息数据库有哪些?都有哪些特点?

药物靶点信息数据库的应用不仅能够高效地扩大靶点信息获取,而且能深化科研人员对于靶点的认识,从而服务于新靶点发现、药物筛选、药物设计、疾病治疗及药理学机制的研究等领域。 药物靶点可以分为受体、酶、离子通道、DNA、激素与生长因子等几种类型。随…

linux服务器上,docker安装nginx

如果出现 Using default tag: latest Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/create?fromImagenginx&taglatest": dial unix /va…

不衔接的两个视频能拼在一起吗?怎么把视频拼接起来?

怎么把视频拼接起来?相信大家在平时刷小视频的时候,都看到过视频合集,例如搞笑视频合集、综艺片段合集、变装合集等等。其实这些视频合集都是通过视频拼接来完成的,只需短短几分钟就能通过这些视频获得愉悦体验,非常适…

一学就会-----删除链表中的重复节点

文章目录 题目描述思路一代码示例思路二代码示例 题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 图片示例: 思路一 解决该问题较简单,且在…

光纤跳线性能测试科普

光纤跳线是一种用于连接光纤设备或光纤网络的光学传输线路,它由两个光纤连接器和一段光纤组成。光纤跳线的质量直接影响着光信号的传输效率和稳定性,因此需要进行一些测试来保证其性能。 一、测试类型 光纤跳线性能测试主要有以下四种: 极性…

【基于容器的部署、扩展和管理】3.10 云原生容器运行时环境和配置管理

往期回顾: 第一章:【云原生概念和技术】 第二章:【容器化应用程序设计和开发】 第三章:【3.1 容器编排系统和Kubernetes集群的构建】 第三章:【3.2 基于容器的应用程序部署和升级】 第三章:【3.3 自动…

运维圣经:Webshell应急响应指南

目录 Webshell简介 Webshell检测手段 Webshell应急响应指南 一. Webshell排查 二. 确定入侵时间 三. Web日志分析 四. 漏洞分析 五. 漏洞复现 六. 清除Webshell并修复漏洞 七. Webshell防御方法 Webshell简介 Webshell通常指以JSP、ASP、 PHP等网页脚本文件形式存在…

kubesphere jenkins 构建java项目报错Could not parse metadata

kubesphere jenkins 构建java项目报错Could not parse metadata 问题描述: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.4:install (default-install) on project common-plugin-starter: Failed to install metadata com.n…

struct | 详解C语言结构体

结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。 结构体和其他类型基础数据类型一样,例如 int 类型,char类型;只不过结构体可以做成你想要的数据类型,以方便日后的使用。 在实际项目…

STM32单片机(六)TIM定时器 -> 第二节:TIM定时中断练习(定时器定时中断和定时器外部时钟)

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要…