【并发】第二篇 ThreadLocal详解

news/2024/4/29 0:09:22/文章来源:https://blog.csdn.net/weixin_44167408/article/details/136733686

导航

    • 一. ThreadLocal 简介
    • 二. ThreadLocal 源码解析
      • 1. get
      • 2. set
      • 3 .remove
      • 4. initialValue
    • 三. ThreadLocalMap 源码分析
      • 1. 构造方法
      • 2. getEntry()
      • 3. set()
      • 4. resize()
      • 5. expungeStaleEntries()
      • 6. cleanSomeSlots()
      • 7. nextIndex()
      • 8. remove()
      • 9. 总结ThreadLocalMap
    • 四. 内存泄漏
      • 1. 产生原理分析
      • 2. 解决方式
    • 五. ThreadLocal 常见的应用场景
      • 1. 数据库连接
      • 2. 事务管理
      • 3. 用户身份认证
      • 4. 线程安全的计数器

在这里插入图片描述

管网上的介绍是这样:
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently ini alized copy of the variable. ThreadLocal instances are typically private sta c fields in classes that wish to associate state with a thread (e.g., a user ID or Transac on ID).
此类提供线程局部变量。这些变量与正常的对应变量的不同之处在于,每个访问一个变量(通过其get或set方法)的线程都有自己的、独立初始化的变量副本。ThreadLocal实例通常是类中的私有静态字段,这些字段希望将状态与线程(例如,用户ID或Transac-on ID)相关联。

一. ThreadLocal 简介

ThreadLocal 是 Java 中的一个类,它提供了线程局部变量的机制。线程局部变量是指每个线程都有自己独立的变量副本,线程之间互不影响。
通常情况下,如果多个线程同时访问一个共享变量,需要进行同步来保证线程安全,如Synchronized。而使用 ThreadLocal 也可以避免线程安全问题,因为每个线程都拥有自己的变量副本,且可以独立地操作自己的变量副本,而不会影响其他线程的副本。线程之间的变量副本互不干扰,保证了线程安全。
在这里插入图片描述

二. ThreadLocal 源码解析

ThreadLocal 类接口很简单,有4个核心内部成员方法

1. get

返回当前线程所对应的线程局部变量

public T get() {// 获取当前线程Thread对象Thread t = Thread.currentThread();// 获取当前线程的ThreadLocalMapThreadLocalMap map = getMap(t);if (map != null) {// 通过ThreadLocal对象获取变量副本ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")// 返回变量副本T result = (T)e.value;return result;}}// 如果ThreadLocalMap为空,或者变量副本未找到,则调用initialValue()方法初始化变量副本// 返回一个nullreturn setInitialValue();
}

ThreadLocalMap 虽然是ThreadLocal的静态内部类, 但在Thread类中也有一个这样类型成员变量,也就是说真正实例化ThreadLocalMap是在Thread类中实现的, 所以getMap()方法实际上返回的是Thread类中成员变量

ThreadLocalMap getMap(Thread t) {return t.threadLocals;}

2. set

设置当前线程的线程局部变量的值

public void set(T value) {// 获取当前线程Thread对象Thread t = Thread.currentThread();// 通过Thread对象获取ThreadLocalMap对象ThreadLocalMap map = getMap(t);if (map != null)// 如果ThreadLocalMap对象存在,则直接设置变量副本map.set(this, value); else// 如果ThreadLocalMap对象不存在,则创建一个新的ThreadLocalMap对象,并设置变量副本createMap(t, value);}

3 .remove

将当前线程局部变量的值删除, 目的是为了减少内存的占用, 避免内存泄漏
该方法是 JDK 5.0 新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收, 所以显式调用该方法清除线程的局部变量并不是必须的操作, 但它可以加快内存回收的速度。

public void remove() {//获取当前线程的ThreadLocalMap ThreadLocalMap m = getMap(Thread.currentThread());if (m != null)//this指当前ThreadLocal实例//ThreadLocalMap中的Entry[]数组中,删除Entry[]数组中使用当前ThreadLocal实例作为key的Entrym.remove(this);}

4. initialValue

返回该线程局部变量的初始值
该方法是一个 protected 的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用 get() 或 set(Object)时才执行,并且仅执行1次。ThreadLocal 中的缺省实现直接返回一 个null。

protected T initialValue() {return null;
}

三. ThreadLocalMap 源码分析

每个线程所拥有的变量的副本数是不定的,有些线程可能有一个,有些线程可能有 2个甚至更多, 则线程内部存放变量副本需要一个容器, 而且容器要支持快速存取, 所以在每个线程内部都可以持有一个 Map 来支持多个变量 副本,这个Map被称为ThreadLocalMap。

static class ThreadLocalMap {/*** Entry数组,用于存储ThreadLocal与变量副本之间的映射关系*/static class Entry extends WeakReference<ThreadLocal<?>> {//变量副本Object value;//key-ThreadLocal实例  value-变量副本Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}// 数组的大小必须为 2 的次幂private static final int INITIAL_CAPACITY = 16;// Entry对象数组,用于存储ThreadLocal与变量副本之间的映射关系private Entry[] table;// 记录当前数组中实际存在元素个数private int size = 0;// ThreadLocalMap的阈值,当size超过该值时进行扩容操作

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

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

相关文章

HarmonyOS 应用开发之显式Want与隐式Want匹配规则

在启动目标应用组件时&#xff0c;会通过显式 Want 或者隐式 Want 进行目标应用组件的匹配&#xff0c;这里说的匹配规则就是调用方传入的 want 参数中设置的参数如何与目标应用组件声明的配置文件进行匹配。 显式Want匹配原理 显式 Want 匹配原理如下表所示。 名称类型匹配…

NanoMQ的安装与部署

本文使用docker进行安装&#xff0c;因此安装之前需要已经安装了docker 拉取镜像 docker pull emqx/nanomq:latest 相关配置及密码认证 创建目录/usr/local/nanomq/conf以及配置文件nanomq.conf、pwd.conf # # # # MQTT Broker # # mqtt {property_size 32max_packet_siz…

使用苹果应用商店上架工具实现应用快速审核与发布

摘要 移动应用app上架是开发者关注的重要环节&#xff0c;但常常会面临审核不通过等问题。为帮助开发者顺利完成上架工作&#xff0c;各种辅助工具应运而生。本文探讨移动应用app上架原理、常见辅助工具功能及其作用&#xff0c;最终指出合理使用工具的重要性。 引言 移动应…

第4章.精通标准提示,引领ChatGPT精准输出

标准提示 标准提示&#xff0c;是引导ChatGPT输出的一个简单方法&#xff0c;它提供了一个具体的任务让模型完成。 如果你要生成一篇新闻摘要。你只要发送指示词&#xff1a;汇总这篇新闻 : …… 提示公式&#xff1a;生成[任务] 生成新闻文章的摘要&#xff1a; 任务&#x…

Stable Diffusion WebUI 生成参数:脚本(Script)——提示词矩阵、从文本框或文件载入提示词、X/Y/Z图表

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 大家好,我是水滴~~ 在本篇文章中,我们将深入探讨 Stable Diffusion WebUI 的另一个引人注目的生成参数——脚本(Script)。我们将逐一细说提示词矩阵、从文本框或文件导入提示词,…

跑腿小程序|基于微信小程序的跑腿平台小程序设计与实现(源码+数据库+文档)

跑腿平台小程序目录 目录 基于微信小程序的跑腿平台小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2、跑腿任务管理 3、任务类型管理 4、公告信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、…

如何安全地添加液氮到液氮罐中

液氮是一种极低温的液体&#xff0c;它在许多领域广泛应用&#xff0c;但在处理液氮时需谨慎小心。添加液氮到液氮罐中是一个常见的操作&#xff0c;需要遵循一些安全准则以确保操作人员的安全和设备的完整性。 选择合适的液氮容器 选用专业设计用于存储液氮的容器至关重要。…

SnapGene 5 for Mac 分子生物学软件

SnapGene 5 for Mac是一款专为Mac操作系统设计的分子生物学软件&#xff0c;以其强大的功能和用户友好的界面&#xff0c;为科研人员提供了高效、便捷的基因克隆和分子实验设计体验。 软件下载&#xff1a;SnapGene 5 for Mac v5.3.1中文激活版 这款软件支持DNA构建和克隆设计&…

线性代数 - 应该学啥 以及哪些可以交给计算机

AI很热&#xff0c;所以小伙伴们不免要温故知新旧时噩梦 - 线代。 &#xff08;十几年前&#xff0c;还有一个逼着大家梦回课堂的风口&#xff0c;图形学。&#xff09; 这个真的不是什么美好的回忆&#xff0c;且不说老师的口音&#xff0c;也不说教材的云山雾绕&#xff0c;单…

JVM(一)——内存结构

一. 前言 1、什么是 JVM? 1&#xff09;定义&#xff1a; Java Virtual Machine - java 程序的运行环境&#xff08;java 二进制字节码的运行环境&#xff09; 2&#xff09;好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收功能数组下标越…

React Native 应用打包上架

引言 在将React Native应用上架至App Store时&#xff0c;除了通常的上架流程外&#xff0c;还需考虑一些额外的优化策略。本文将介绍如何通过配置App Transport Security、Release Scheme和启动屏优化技巧来提升React Native应用的上架质量和用户体验。 配置 App Transport…

基于振弦采集仪的土体变形监测与分析

基于振弦采集仪的土体变形监测与分析 工程监测振弦采集仪是一种专用于工程监测中的振弦测量的仪器。它能够实时采集及记录结构物的振动信号&#xff0c;以评估结构物的健康状况、安全性能等。它通常由振弦传感器、数据采集模块和数据处理软件组成。振弦传感器负责测量结构物的…

uniApp使用XR-Frame创建3D场景(5)材质贴图的运用

上一篇讲解了如何在uniApp中创建xr-frame子组件并创建简单的3D场景。 这篇我们讲解在xr-frame中如何给几何体赋予贴图材质。 先看源码 <xr-scene render-system"alpha:true" bind:ready"handleReady"><xr-node><xr-assets><xr-asse…

联想 lenovoTab 拯救者平板 Y700 二代_TB320FC原厂ZUI_15.0.677 firmware 线刷包9008固件ROM root方法

联想 lenovoTab 拯救者平板 Y700 二代_TB320FC原厂ZUI_15.0.677 firmware 线刷包9008固件ROM root方法 ro.vendor.config.lgsi.market_name拯救者平板 Y700 ro.vendor.config.lgsi.en.market_nameLegion Tab Y700 #ro.vendor.config.lgsi.short_market_name联想平板 ZUI T # B…

2024多云管理平台CMP排名看这里!

随着云计算技术的迅猛发展&#xff0c;多云管理平台CMP应运而生。多云管理平台CMP仅能够简化对多个云环境的统一管理&#xff0c;还能提高资源利用效率和降低成本。因此了解多云管理平台CMP品牌是必要的。2024多云管理平台CMP排名看这里&#xff01;仅供参考哈&#xff01; 20…

Java八股文(JVM)

Java八股文のJVM JVM JVM 什么是Java虚拟机&#xff08;JVM&#xff09;&#xff1f; Java虚拟机是一个运行Java字节码的虚拟机。 它负责将Java程序翻译成机器代码并执行。 JVM的主要组成部分是什么&#xff1f; JVM包括以下组件&#xff1a; ● 类加载器&#xff08;ClassLoa…

【SpringBoot从入门到精通】03_SpringBoot自动配置原理

三、SpringBoot自动配置原理 我们通过编写SpringBoot HelloWorld程序&#xff0c;体会到了其强大与便捷&#xff0c;它的这些功能都是基于SpringBoot的依赖管理与自动配置。 3.1 核心特性 依赖管理 父项目做依赖管理 <!-- 当前项目的父项目&#xff1a;依赖管理 --> &…

MySQL进阶-----索引的语法与SQL性能分析

目录 前言 一、索引语法 1.SQL语法 2.案例演示 二、SQL性能分析 三、慢查询日志 1.开启日志 2.测试样例 四、profile详情 1.开启profile 2.profile测试SQL语句 五、explain详情 1.语法结构 2.执行顺序示例&#xff08;id&#xff09; 3.执行性能示例(type) 前言 本…

每日一题--最长连续序列

洛阳春-岑参 人到洛阳花似锦&#xff0c;偏我来时不逢春。 谁道三冬无春色&#xff0c;冰山高处万里银 目录 题目描述 思路分析 方法及其时间复杂度 法一 暴力枚举&#xff1a; 法二 哈希表遍历&#xff1a; 法三 并查集&#xff1a; 个人总结 题目描述 128. 最长连续序…

JVM快速入门(2)HotSpot和堆、新生区、永久区、堆内存调优、JProfiler工具分析OOM原因、GC(垃圾回收)、JVM经典面试笔试题整理

5.6 HotSpot和堆 5.6.1 Hotspot 三种JVM&#xff1a; Sun公司&#xff0c;HotspotBEA&#xff0c;JRockitIBM&#xff0c;J9 VM&#xff0c;号称是世界上最快的Java虚拟机 我们一般学习的是&#xff1a;HotSpot 5.6.2 堆 Heap&#xff0c;一个JVM只有一个堆内存&#xff0c…