ThreadLocal 的概念及使用场景(登录状态验证)

一、ThreadLocal 的概念

ThreadLocal 是 Java 中用于解决多线程并发问题的类。它通过为每个线程提供单独的变量副本,使得每个线程都可以对这些变量进行独立的访问和修改,而不影响其他线程中的相同变量。

简单来说,ThreadLocal 为每个使用它的线程创建一个独立的变量副本。多个线程之间的数据彼此独立,互不干扰,非常适合需要隔离线程之间的数据共享的场景。

二、ThreadLocal 的使用场景

  1. 用户上下文信息存储:在 Web 应用中,通常需要在不同的组件中共享用户会话的数据。例如,用户登录状态的信息,使用 ThreadLocal 可以保证每个用户线程都有自己独立的上下文。
  2. 数据库连接管理:在多线程环境中,每个线程都有自己的数据库连接,使用 ThreadLocal 可以确保每个线程只使用属于自己的连接,避免出现混乱。
  3. 事务管理:当一个线程在执行事务时,ThreadLocal 可以用来存储事务对象,以保证事务的独立性和一致性。
  4. 线程独立的资源管理:例如,格式化器(SimpleDateFormat)是线程不安全的类,将它放入 ThreadLocal 可以保证每个线程都有自己的格式化器实例,从而避免线程安全问题。

三、ThreadLocal 的使用案例

public class ThreadLocalExample {// 创建一个 ThreadLocal 变量private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);public static void main(String[] args) {Runnable task = () -> {for (int i = 0; i < 5; i++) {Integer value = threadLocal.get();threadLocal.set(value + 1);System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());}};Thread thread1 = new Thread(task);Thread thread2 = new Thread(task);thread1.start();thread2.start();}
}

 案例中ThreadLocal.withInitial(() -> 0) 用于为每个线程提供一个初始值为 0 的 ThreadLocal 变量。每个线程在自己的上下文中对变量进行递增,互不干扰,因此每个线程的输出是独立的。

四、ThreadLocal 的原理

ThreadLocal 的核心是通过为每个线程分配一个单独的变量副本实现的。在每个线程内部都有一个 ThreadLocalMap,当你调用 ThreadLocalset()get() 方法时,实际是在当前线程的ThreadLocalMap 中操作。

具体原理如下:

  1. ThreadLocal 与线程:每个线程内部都有一个 ThreadLocalMap 类型的成员变量,这个 ThreadLocalMap 是专门用来存储与 ThreadLocal 相关的数据的。
  2. ThreadLocalMap 结构ThreadLocalMap 的键是 ThreadLocal 对象本身,值则是要存储的数据副本。通过这种方式,线程可以为每一个 ThreadLocal 实例维护独立的数据。
  3. set() 方法:当你调用 ThreadLocalset() 方法时,会将值放入当前线程的 ThreadLocalMap 中,以当前 ThreadLocal 实例为键,存储相应的数据。
  4. get() 方法:get() 方法则是从 ThreadLocalMap 中获取当前线程对应的值,保证每个线程只能访问自己的数据。

五、ThreadLocal 的注意事项

  • 内存泄漏问题ThreadLocal 如果没有被正确地回收,可能会导致内存泄漏。ThreadLocalMap 中的键是 ThreadLocal 的弱引用,如果线程长期运行而没有手动清理 ThreadLocal,那么 ThreadLocal 对象可能被回收,而值却不会被自动回收,从而引发内存泄漏。通常可以在不再使用 ThreadLocal 时调用 remove() 方法来避免这种问题。

    threadLocal.remove(); // 在使用完后,手动移除
    
  • 不适用于共享数据ThreadLocal 适合存储每个线程的独立数据,而不是用于在线程之间共享数据。如果需要在不同线程之间共享数据,应该考虑使用其他并发工具(如 synchronizedReentrantLockConcurrentHashMap 等)。

  • 线程生命周期ThreadLocal 存储的数据与线程的生命周期有关。当线程结束时,ThreadLocal 中的数据也会被回收。因此,适合用于临时存储线程的状态信息,而不适合用于长生命周期的数据存储。

六、登录状态验证场景使用

1.用户身份信息管理: 在处理 Web 请求时,每个请求都是由不同的线程处理的。ThreadLocal 可以用来存储每个请求的用户身份信息,确保在处理请求的各个阶段都能安全地访问当前用户的上下文信息。

public class UserContext {private static ThreadLocal<User> userThreadLocal = new ThreadLocal<>();public static void setUser(User user) {userThreadLocal.set(user);}public static User getUser() {return userThreadLocal.get();}public static void clear() {userThreadLocal.remove();}
}
2.在处理请求时,存储用户信息:
UserContext.setUser(currentUser);
在不同的业务逻辑中,还可以通过 UserContext.getUser() 获取当前线程的用户信息。

七、总结

  • ThreadLocal 是 Java 提供的一种存储每个线程独立变量的方法,非常适合处理每个线程需要有独立变量副本的场景。
  • 适用场景ThreadLocal 适合用户上下文信息存储、事务管理、数据库连接管理等需要在线程中共享数据但与其他线程独立的数据。
  • 优点:它的最大优点是避免了显式的同步操作,提供了线程安全的数据隔离。
  • 注意事项:要小心使用,防止内存泄漏。适时调用 remove() 方法清理数据是最佳实践。

在登录系统中,比如登录状态验证中,ThreadLocal 可以很好地保证每个用户请求的线程都有自己的用户信息,从而避免了线程数据的干扰,确保系统的安全性和稳定性。

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

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

相关文章

Android——多线程、线程通信、handler机制

Android——多线程、线程通信、handler机制 模拟网络请求&#xff0c;会阻塞主线程 private String getStringForNet() {StringBuilder stringBuilder new StringBuilder();for (int i 0; i < 100; i) {stringBuilder.append("字符串" i);}try {Thread.sleep(…

Jumpserver

概述 一款开源的堡垒机&#xff0c;可使系统的管理员和开发人员安全的连接到企业内部服务器上执行操作&#xff0c;是一款非常安全的远程连接工具。 4A 身份验证授权控制账号管理安全审计 安装 [rootjumpserver project]# tar -xf jumpserver-offline-installer-v2.28.6-amd64…

【专题】2024年全球生物医药交易报告汇总PDF洞察(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p38191 在当今复杂多变的全球经济环境下&#xff0c;医药行业正面临着诸多挑战与机遇。2024 年&#xff0c;医药行业的发展态势备受关注。 一方面&#xff0c;全球生物医药交易活跃&#xff0c;2021 - 2023 年的交易中&#xff0c;已…

统信UOS开发环境支持rust

集成了Rust编译器和包管理工具,支持系统级编程、网络应用等多场景,为开发者提供丰富的库支持。 文章目录 一、环境部署1. rust开发环境安装2. rust开发环境配置二、代码示例三、常见问题1. 借用和所有权问题2. 编译器错误和警告一、环境部署 1. rust开发环境安装 rust是一门…

Addressables资源打包(AA包)代码中改变远程地址

接着上一篇“Unity资源打包Addressable AA包” 还是先贴代码 LoadPath.cs 中定义一个远程服务器的地址&#xff0c;这个地址将来在代码中会修改 namespace HFS {public class LoadPath{public static string Path "http://172.18.216.168:6565/HFS/1/";} } 远程服…

linux基础-完结(详讲补充)

linux基础-完结 一、Linux目录介绍 二、基础命令详细讲解 1. ls&#xff08;列出目录内容&#xff09; 2. cd&#xff08;更改目录&#xff09; 3. clear&#xff08;清除终端屏幕&#xff09; 4. pwd(显示你当前所在的目录) 5. vim(文本编辑器) 6. touch&#xff08;创…

开启鸿蒙开发之旅:准备篇

写在前面 Q:为什么要学习鸿蒙&#xff1f; A:没有特定的理由&#xff0c;有可能是因为大环境不好的原因&#xff0c;大家越来越卷&#xff0c;技术革新越来越快&#xff0c;如果手里多掌握一门技术&#xff0c;心里会更有底气一些。再一个自己只有前端开发经验&#xff0c;平时…

倒计时3天 | 2024 CCF中国开源大会仪式解读

点击蓝字 关注我们 CCF Opensource Development Committee CCF 大会简介 2024 CCF中国开源大会&#xff08;CCF ChinaOSC&#xff09;将于2024年11月9日至10日在深圳召开。本届大会由中国计算机学会主办&#xff0c;CCF开源发展委员会、鹏城实验室、新一代人工智能产业技术创新…

硬件基础17 半导体存储器——随机存取存储器RAM

目录 一、异步SRAM 二、同步SRAM 三、DRAM 四、字长位数扩展 五、字数的扩展 RAM是另一大类存储器&#xff0c;它与ROM的最大区别就是数据易失性&#xff0c;一旦失去电源供电&#xff0c;所存储的数据立即丢失。最大优点是可以随时快速地从其中任一指定地址读出&#xff…

安装VMware Tools选项显示灰色以及连接不上服务器,下载出错的正确解决办法

1.显示灰色解决办法&#xff1a; 解决办法&#xff1a; 关闭虚拟机 选择“虚拟机设置”&#xff0c;分别添加一个“软盘”和一个“CD/DVD”&#xff0c;并将所有软盘和CD/DVD&#xff08;包括自带的&#xff09;“连接”选项全部更改为“使用物理驱动器” 2.关闭虚拟机重启即…

git中使用tag(标签)的方法及重要性

在Git中打标签&#xff08;tag&#xff09;通常用于标记发布版本或其他重要提交。 Git中打标签的步骤&#xff1a; 列出当前所有的标签 git tag创建一个指向特定提交的标签 git tag <tagname> <commit-hash>创建一个带注释的标签&#xff0c;通常用于发布版本 git…

BMC运维管理:IPMI实现服务器远控制

IPMI实现服务器远控制 实操一、使用IPMI重置BMC用户密码实操二、使用IPMI配置BMC的静态IP实操三、IPMI实现BMC和主机控制操作实操四、ipmitool查看服务器基本信息实操五、ipmitool实现问题定位BMC(Baseboard Management Controller,基板管理控制器)是服务器硬件的一个独立管…

Android Profiler 内存分析

Android studio&#xff08;下面简称AS&#xff09;为App提供的性能分析工具&#xff0c;在AS3.0替换掉旧的分析工具&#xff0c;对于其使用方法&#xff0c;官方也有对应的介绍&#xff1a;Android Profiler 对于使用方法&#xff0c;我只用到比较简单的功能&#xff0c;高级的…

vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法

1、先上个截图&#xff1a; 说明&#xff1a;拖动上面的分隔栏就可以实现&#xff0c;改变左右区域的大小。 2、上面的例子来自官网的&#xff1a; Container 布局容器 | Element Plus 3、拖动的效果来自&#xff1a; https://juejin.cn/post/7029640316999172104#heading-1…

adminPage-vue3依赖DetailsModule版本说明:V1.2.1——1) - 新增span与labelSpan属性

文章目录 更新内容DetailsModuleAPI汇总属性自定义对象config.list(array<object> 类型) 使用span属性&#xff08;24栅格系统&#xff09; 更新内容 新增span与labelSpan属性&#xff0c;当使用span属性时将不适用默认的布局&#xff0c;如果24栅格系统进行重新布局 D…

系统聚类的分类数确定——聚合系数法

breast_cancer数据集分析——乳腺癌诊断 #读取乳腺癌数据 import pandas as pd import numpy as np from sklearn.datasets import load_breast_cancer data load_breast_cancer() X data.data y data.target.. _breast_cancer_dataset:Breast cancer wisconsin (diagnosti…

Android 实现柱形图

在 Android 中实现柱状图&#xff0c;可以使用流行的图表库 MPAndroidChart&#xff0c;它支持多种类型的图表&#xff0c;包括柱状图、折线图、饼图等。下面是一个基本的柱状图实现步骤&#xff0c;具体分为以下几个部分&#xff1a; 1. 添加依赖 首先&#xff0c;你需要在 …

dolphin 配置data 从文件导入hive 实践(一)

datax 支持多种数据源的相互读写&#xff0c;作为开源软件&#xff0c;提供了离线采集功能&#xff0c;方便系统开发&#xff0c;过程中遇到诸多配置&#xff0c;需要开发者自己探索&#xff0c;免费同样有成本 配置模板 {"setting": {},"job": {"s…

AUTOSAR CP Ethernet State Manager(EthSM)规范的主要功能以及工作原理导读

AUTOSAR Ethernet State Manager&#xff08;以下简称EthSM&#xff09;规范的主要功能 AUTOSAR Ethernet State Manager&#xff08;以下简称EthSM&#xff09;规范的主要功能包括&#xff1a; 通信控制 网络模式管理&#xff1a;为通信管理器&#xff08;ComM&#xff09;提…

深度学习中的感受野:从基础概念到多层次特征提取

在深度学习&#xff0c;特别是计算机视觉任务中&#xff0c;感受野&#xff08;Receptive Field&#xff09;是一个至关重要的概念。它指的是在神经网络中某一层的神经元在输入图像上“看到”的区域大小。感受野的大小影响了网络能捕捉的特征层级&#xff0c;从而决定了它的特征…