线程变量ThreadLocal用于解决多线程并发时访问共享变量的问题。

ThreadLocal介绍

ThreadLocal叫做线程变量,用于解决多线程并发时访问共享变量的问题。意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

 所谓的共享变量指的是在堆中的实例、静态属性和数组;对于共享数据的访问受Java的内存模型(JMM)的控制,其模型如下

ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:

因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来。
既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。
ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。

总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景

下图可以增强理解:
 

ThreadLocal的简单使用 

public class Example {  
    // 创建一个 ThreadLocal 变量  
    private static final ThreadLocal<Integer> threadLocal = new ThreadLocal<>();  
  
    public static void main(String[] args) {  
        // 创建两个线程  
        Thread thread1 = new Thread(() -> {  
            // 在线程1中设置 ThreadLocal 变量的值  
            threadLocal.set(1);  
            System.out.println(Thread.currentThread().getName() + " value: " + threadLocal.get());  
        });  
  
        Thread thread2 = new Thread(() -> {  
            // 在线程2中设置 ThreadLocal 变量的值  
            threadLocal.set(2);  
            System.out.println(Thread.currentThread().getName() + " value: " + threadLocal.get());  
        });  
  
        // 启动线程  
        thread1.start();  
        thread2.start();  
    }  
}

Threadlocal 内存溢出问题

ThreadLocal在Java中广泛用于实现线程本地存储,为每个线程提供一个独立的变量副本。然而,不正确的使用可能会导致内存溢出或其他问题。以下是ThreadLocal可能导致内存溢出的原因及解决方法:

内存泄露原因:ThreadLocalMap是ThreadLocal的内部类,用于存储每个线程的变量副本。在ThreadLocalMap中,key是弱引用,而value是强引用。这意味着当没有外部强引用指向ThreadLocal对象时,它可能会被垃圾回收。但是,由于ThreadLocalMap中的key是弱引用,它们在GC时可能会被回收。如果此时ThreadLocal对象仍然没有被回收,那么ThreadLocalMap中就会出现key为null的Entry。

使用static的ThreadLocal:静态的ThreadLocal会延长其生命周期,可能导致内存泄漏。因为静态的ThreadLocal对象在整个应用程序运行期间都存在,如果不正确地使用它,可能会导致内存泄漏。

未调用get(), set(), remove()方法:如果分配了ThreadLocal对象但不再调用其get(), set(), remove()方法,那么ThreadLocal对象可能不会被回收,从而导致内存泄漏。

解决策略:

为避免内存泄漏,应确保对ThreadLocal的使用后调用remove()方法来清除对应的值和引用。
使用弱引用的key可以帮助ThreadLocal自动清理过期的节点,从而避免内存泄漏。
尽量避免使用静态的ThreadLocal,或者确保在使用后正确清理资源。
总之,要正确使用ThreadLocal并避免内存泄漏,需要了解其内部机制和工作原理,并确保在使用时遵循最佳实践。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

12. Nginx进阶-Location

简介 Nginx的三大区块 在Nginx中主要配置包括三个区块&#xff0c;结构如下&#xff1a; http { #协议级别include /etc/nginx/mime.types;default_type application/octet-stream;log_format main $remote_addr - $remote_user [$time_local] "$r…

ssl证书无效是否继续访问啥意思

SSL证书&#xff08;Secure Sockets Layer&#xff09;是现代互联网通信安全的基础组成部分&#xff0c;尤其对于涉及敏感信息交换的HTTPS站点至关重要。当浏览器提示“SSL证书无效”时&#xff0c;这意味着浏览器无法验证网站的身份或确定其加密连接的安全性。这种情况下&…

基于Python+Flask实现一个TODO任务管理系统网站

随着科技的进步&#xff0c;数字化的任务清单逐渐成为生活中不可或缺的一部分。它们不仅可以帮助我们跟踪日常任务&#xff0c;还可以提高效率。但是&#xff0c;你是否考虑过自己制作一个任务管理系统呢&#xff1f; 好消息是&#xff0c;使用Python和Flask&#xff0c;我们可…

器件选型【MOS,三极管篇】

三极管篇&#xff1a; 三极管的两大作用&#xff1a;做开关使用和放大电流 一句话总结&#xff1a;三极管选型主要考虑集电极最大允许电流&#xff0c;集电极-发射极反向击穿电压&#xff0c;集电极最大允许耗散功率&#xff0c;特征频率&#xff0c;封装形式&#xff0c;工作…

电脑防火墙怎么关?分享2个简单方法

在当今数字化时代&#xff0c;保护计算机免受网络威胁和恶意软件攻击是至关重要的。电脑防火墙作为一种重要的安全措施&#xff0c;可以有效地阻止未经授权的网络访问&#xff0c;保障您的个人信息和数据安全。 然而&#xff0c;有时候在特定情况下&#xff0c;您可能需要临时…

【ES入门一:基础概念】

集群层面上的基础概念 集群 由多个es实例组成的叫做集群 节点 单个ES的服务实例叫做节点。每个实例都有自己的名字&#xff0c;就是在配置文件中配置的‘node.name’中的内容。为了标识每个节点&#xff0c;每个节点启动后都会分配一个UID&#xff0c;存储在data目录。每个…

【leetcode】三数之和 双指针

/*** param {number[]} nums* return {number[][]}*/ var threeSum function(nums) {nums.sort((a,b)>a-b);let result[];for(let i0;i<nums.length-2;i){if(nums[i]>0) return result;//因为求三数之和等于0&#xff0c;如果第一个数已经大于0&#xff0c;后面肯定无…

数仓实战——懂车帝数据指标体系建设和应用实践

目录 一、如何建立指标体系规范 1.1 懂车帝业务介绍 1.2 为什么要做指标体系规范 1.3 DataLeap 指标管理平台 1.4 指标体系建设框架 1.5 指标元数据管理规范 二、指标模型建设在数仓工作中的收敛 2.1 指标模型建设存在的问题 2.2 指标模型数仓层级建设标准 2.3 从指标…

stm32f103zet6笔记1-led工程

1、选择串口调试 2、LED0连接到PB5&#xff0c;PB5设置为推挽输出。PE5同理。 3、生成成对的.c,.h文件。 4、debugger选择j-link。 5、connection选择SWD。 6、编写bsp_led.c,bsp_led.h文件。 7、下载调试&#xff0c;可以看到LED0 500ms闪烁一次&#xff0c;LED1 1000ms闪烁一…

Node.js与Webpack笔记(一)

这里使用的16.19.0版本&#xff0c;官网和github没找到&#xff0c;去黑马2023年课程里找 篇幅较大会卡&#xff0c;此篇幅不写Webpack部分&#xff0c;留着下一篇 初识 1.什么是Node.js? Node.js 是一个独立的 JavaScript 运行环境&#xff0c;能独立执行 JS 代码&#xff…

基于机器学习的曲面拟合方法

随着科技的不断发展&#xff0c;机器学习成为了最近最热门的技术之一&#xff0c;也被广泛应用于各个领域。其中&#xff0c;基于机器学习的曲面拟合方法也备受研究者们的关注。曲面拟合是三维模型处理中的重要技术&#xff0c;其目的是用一组数据点拟合出平滑的曲面&#xff0…

STM32启动过程及反汇编

STM32从Flash启动的过程&#xff0c;主要是从上电复位到main函数的过程&#xff0c;主要有以下步骤&#xff1a; 1.初始化堆栈指针 SP_initial_sp&#xff0c;初始化 PC 指针Reset_Handler 2.初始化中断向量表 3.配置系统时钟 4.调用 C 库函数_main 初始化用户堆栈&#xf…

【软件测试】Postman中变量的使用

Postman中可设置的变量类型有全局变量&#xff0c;环境变量&#xff0c;集合变量&#xff0c;数据变量及局部变量。区别则是各变量作用域不同&#xff0c;全局变量适用于所有集合&#xff0c;环境变量适用于当前所选环境&#xff08;所有集合中均可使用不同环境变量&#xff09…

常用通讯协议的理解

一、通讯的一些基本认知 1、什么是异步或同步通信 异步通信在发送字符时&#xff0c;所发送的字符之间的时间间隔可以是任意的。发送端可以在任意时刻开始发送字符&#xff0c;因此必须在每一个字符的开始和结束的地方加上标志&#xff0c;即加上开始位和停止位&#xff0c;以…

通义千问1.5(Qwen1.5)大语言模型在PAI-QuickStart的微调与部署实践

作者&#xff1a;汪诚愚&#xff08;熊兮&#xff09;、高一鸿&#xff08;子洪&#xff09;、黄俊&#xff08;临在&#xff09; Qwen1.5&#xff08;通义千问1.5&#xff09;是阿里云最近推出的开源大型语言模型系列。作为“通义千问”1.0系列的进阶版&#xff0c;该模型推出…

为什么 Java 中只有值传递?

为什么 Java 中只有值传递&#xff1f; 开始之前&#xff0c;我们先来搞懂下面这两个概念&#xff1a; 形参&实参值传递&引用传递 形参&实参 方法的定义可能会用到 参数&#xff08;有参的方法&#xff09;&#xff0c;参数在程序语言中分为&#xff1a; 实参…

TCP和UDP可以使用同一个端口号吗?

TCP和UDP可以使用同一个端口号吗&#xff1f; 首先说答案&#xff1a;可以。怎么理解呢&#xff1f; 我想这个问题要从计算机网络通信谈起&#xff0c;学过计算机网络的同学&#xff0c;可能都还记得7层或者4层网络模型&#xff0c;TCP/UDP属于其中的传输层协议&#xff0c;在…

一个完整的Flutter项目的基本构成

目录 1.页面跳转2.本地数据库和读取2.1 在pubspec.yaml中添加数据库框架依赖2.2 创建db.dart 初始化数据库并创建表2.3 安装JsonToDart插件2.4 创建实体类 user_bean.dart2.5 增删改查&#xff1a; 3.网络请求数据解析UI渲染 本篇主要总结下一个完整的Flutter项目有哪些基本构成…

STM32基础--初识 STM32

什么是 STM32 对于STM32&#xff0c;从字面意思上来理解&#xff0c;ST是意法半导体&#xff0c;M是Microelectronics的缩写&#xff0c;其中32表示的是32位&#xff0c;那么整合起来理解就是&#xff1a;STM32就是指的ST公司开发的32位微控制器。在如今的32位控制器中&#x…

mq基础类设计

消息队列就是把阻塞队列这样的数据结构单独提取成一个程序独立进行部署。——>实现生产者消费者模型。 但是阻塞队列是在一个进程内部进行的&#xff1b; 消息队列是在进程与进程之间进行实现的&#xff0c; 解耦合&#xff1a;就是在分布式系统中&#xff0c;A服务器调用B…