谈一谈Java的ThreadLocal

news2024/11/20 15:27:22

目录

先说原理:

再上代码:

运行结果:


先说原理:

ThreadLocal 是一个本地线程副本变量工具类,它可以在每个线程中创建一个副本变量,每个线程可以独立地修改自己的副本变量,而不会影响其他线程的副本变量。它的实现原理可以简单概括如下:

  1. ThreadLocal 内部维护了一个 Map 对象,用于存储每个线程的副本变量。Map 的键为线程对象,值为对应线程的副本变量。
  2. 在每个线程中,ThreadLocal 实例会创建一个唯一的 ThreadLocalMap 对象,用于存储该线程的所有副本变量。ThreadLocalMap 是一个自定义的哈希表数据结构继承自 WeakReference,它的键为 ThreadLocal 对象,值为对应线程的副本变量。
  3. 在创建 ThreadLocal 实例时,实际上是在当前线程的 ThreadLocalMap 中新增一个键值对,其中键为当前 ThreadLocal 对象,值为初始化的副本变量。
  4. 当需要获取当前线程的副本变量时,ThreadLocal 实例会先获取当前线程的 ThreadLocalMap,再通过当前 ThreadLocal 对象作为键来获取对应的副本变量。由于每个线程独立维护自己的 ThreadLocalMap,所以不同线程的相同 ThreadLocal 对象对应的副本变量也是不同的。
  5. 当一个线程结束时,它持有的所有 ThreadLocalMap 中的键值对会成为垃圾对象,但由于 ThreadLocalMap 的键是 WeakReference 类型,所以这些键可能被垃圾回收器回收,但值对象不会被回收,从而导致内存泄漏。为了解决这个问题,ThreadLocal 内部使用了 ThreadLocalMapexpungeStaleEntry() 方法,定期清除废弃的键值对。

总的来说,ThreadLocal 通过维护一个 Map,为每个线程创建一个独立的 ThreadLocalMap,并使用弱引用来避免内存泄漏,从而实现了在每个线程中创建独立的副本变量,并提供了线程安全的访问方式。

再上代码:

package cn.net.cdsz.ccb.test;

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;

public class test {

        static class ThreadA implements Runnable {
            private ThreadLocal<String> threadLocal;

            public ThreadA(ThreadLocal<String> threadLocal) {
                this.threadLocal = threadLocal;
            }

            @Override
            public void run() {
                threadLocal.set("A");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("ThreadA输出:" + threadLocal.get());
            }
        }
        static class ThreadB implements Runnable {
            private ThreadLocal<String> threadLocal;
            public ThreadB(ThreadLocal<String> threadLocal) {
                this.threadLocal = threadLocal;
            }
            @Override
            public void run() {
                threadLocal.set("B");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("ThreadB输出:" + threadLocal.get());
            }
        }
        public static void main(String[] args) {
            ThreadLocal<String> threadLocal = new ThreadLocal<>();
            new Thread(new ThreadA(threadLocal)).start();
            new Thread(new ThreadB(threadLocal)).start();
        }

}

运行结果:

最常⻅的ThreadLocal使⽤场景为⽤来解决数据库连接、Session管理等。数据库连
接和Session管理涉及多个复杂对象的初始化和关闭。如果在每个线程中声明⼀些
私有变量来进⾏操作,那这个线程就变得不那么“轻量”了,需要频繁的创建和关闭
连接。

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

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

相关文章

【进阶C语言】自定义类型:结构体,枚举,联合

前言 作者简介&#xff1a;热爱跑步的恒川&#xff0c;正在学习C/C、Java、Python等。 本文收录于C语言进阶系列&#xff0c;本专栏主要内容为数据的存储、指针的进阶、字符串和内存函数的介绍、自定义类型结构、动态内存管理、文件操作等&#xff0c;持续更新&#xff01; 相关…

ECM8.0——CCCM相关代码

ECM8.0——CCCM相关代码概览predIntraCCCMxCccmCalcModelsxCccmApplyModelxCccmCreateLumaRefxCccmGetLumaRefBufxCccmGetLumaPuBufxCccmCalcRefAverxCccmCalcRefArea概览 函数名称函数作用predIntraCCCM总体代码&#xff0c;根据CCCM技术预测输出xCccmCalcModels计算CCCM滤波器…

Idea+maven+spring-cloud项目搭建系列--14 整合请求参数校验

前言&#xff1a;当我们在进行web 项目的开发时&#xff0c;对于前端传入的参数&#xff0c;都需要进行一些非空必填等的验证&#xff0c;然后在进行业务逻辑的处理&#xff0c;如果写一堆的if 判断很不优雅&#xff0c;那么有没有好的方式来帮忙处理&#xff0c;本文通过hiber…

光电隔离转换器 直流信号放大器 导轨安装DIN11 IPO OC系列

概述&#xff1a; 导轨安装DIN11 IPO OC系列模拟信号隔离放大器是一种将输入信号隔离放大、转换成按比例输出的直流信号混合集成厚模电路。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等需要直流信号隔离测控的行业。此系列产品内部采用了线性光电隔离技术相…

DSP中定点与浮点运算

一、定点数及其定标 在定点DSP芯片中&#xff0c;采用的是定点数据数值运算&#xff0c;其操作数一般采用整形数来表示。一个整形数的最大表示范围由DSP芯片给定字长决定。字长越长&#xff0c;表示的范围越大&#xff0c;精度越高。 举例16位字长 每个16数位用1个符号位表示正…

九龙证券|这一刻,资本市场进入全新时代!

2023年4月10日&#xff0c;第一批10家主板注册制企业上市鸣锣敲钟&#xff0c;奏响了触及本钱商场灵魂深处革新的序曲。 动能切换中的我国对于高效资源配置的渴望&#xff0c;与革新进行时的本钱商场对于全面注册制的探究&#xff0c;一起凝集成一股连绵有力之暖流&#xff0c;…

学习安全攻防技能30讲-开篇|别说你没有被安全困扰过

文章目录学习安全攻防技能30讲-开篇|别说你没有被安全困扰过研读开篇安全重要吗&#xff1f;安全难学吗&#xff1f;学习安全攻防技能30讲-开篇|别说你没有被安全困扰过 研读开篇 文中说到一个竞赛叫CTF&#xff0c;这个之前从来没有听过的&#xff0c;作为开发人员涨知识了。…

Java封装

Java封装\huge{Java封装}Java封装 JavaJavaJava的三大特征之一。 作用 告知如何设计对象的属性和方法&#xff0c;将对象完全独立起来。 ❗❗封装原则 对象代表什么&#xff0c;就要封装对应的数据&#xff0c;并且提供对应数据的行为。&#xff08;尤其是后半句非常重要&a…

012:Mapbox GL显示弹窗Popup

第012个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中显示弹窗。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共70行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https://xiaozhuan…

PHP医院安全(不良)事件管理系统源码,十多种不良事件类型,上百种报告内容数据表

医院不良事件上报系统源码&#xff0c;PHP医院安全&#xff08;不良&#xff09;事件管理系统源码 技术架构&#xff1a;前后端分离&#xff0c;仓储模式&#xff0c; 开发语言&#xff1a;PHP 开发工具&#xff1a;vscode 前端框架&#xff1a;vue2element 后端框架&…

2023年mathorcupB题城市轨道交通列车时刻表思路分析

B 题 城市轨道交通列车时刻表优化问题 列车时刻表优化问题是轨道交通领域行车组织方式的经典问题之一。 列车时刻表规定了列车在每个车站的到达和出发(或通过)时刻&#xff0c;其在实 际运用过程中&#xff0c;通常用列车运行图来表示。图 1 为某一运行图的示例&#xff0c;图…

文件操作【上篇】

文章目录&#x1f5c3;️1.为什么使用文件&#x1f5c3;️2.什么是文件&#x1f4c1;2.1.程序文件&#x1f4c1;2.2.数据文件&#x1f4c1;2.3.文件名&#x1f5c3;️3.文件的打开和关闭&#x1f4c1;3.1.文件指针&#x1f4c1;3.2.文件的打开和关闭&#x1f5c3;️4.文件的顺序…

I-型糖尿病患者的福音,皮下燃料电池将多余的血糖转化为电能产生胰岛素

I-型糖尿病患者体内不产生胰岛素&#xff0c;患者必须从外部获得激素来调节血糖水平。当前&#xff0c;患者主要通过将胰岛素泵直接连接到身体以获得胰岛素。这些胰岛素泵以及其他医疗器械&#xff08;如起搏器&#xff09;需要可靠的能源供应&#xff0c;主要通过一次性或可充…

#mvn 打包ik分词器报错#

场景&#xff1a;在window上安装ik分词器&#xff0c;需要先mvn打包&#xff0c;结果报错 原因&#xff1a;由于jdk版本的问题导致 解决过程 1&#xff1a;打包流程 git clone https://github.com/medcl/elasticsearch-analysis-ik #git clone https://gitcode.net/mirrors/me…

线性分类算法:逻辑回归和Softmax回归

目录&#xff08;一 &#xff09;逻辑回归1.1 逻辑回归概述&#xff1a;1.2 逻辑回归的作用与Sigmoid 函数&#xff1a;1.2.1 Sigmoid 函数作用1.3 指数族分布1.4 逻辑回归的损失函数1.5逻辑回归如何求解得到最优解模型方法1.6 逻辑回归鸢尾花分类1.7 逻辑回归做多分类&#xf…

拉取gradle项目报错Could not find method compile() for arguments

拉取gradle项目, 依赖拉不下来, 报错如下: Could not find method compile() for arguments XXXXXX on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler. 找了很多篇文章都没有解决,后来在stack overflow上面找到了答案: Note t…

Linux中快速搭建RabbitMQ

目录一、简介1、关于RabbitMQ2、RabbitMQ主要端口介绍二、RabbitMQ安装1、安装依赖项socat2、下载Erlang和RabbitMQ(1) Erlang和RabbitMQ版本关系要求(2) 下载操作系统支持的Erlang和RabbitMQ版本(3) 安装Erlang和RabbitMQ三、启动和关闭1、启动服务2、查看状态3、停止服务4、设…

核心业务3:借款人借款申请

核心业务3&#xff1a;借款人借款申请 1.借款人借款申请业务流程图 2.借款项数据库绑定 ---------------------借款申请流程---------------------- 3.借款申请流程 4.前端代码逻辑 5.后端代码逻辑 ---------------------借款申请流程---------------------- 核心业务3&…

用SSH登陆Centos系统时,命令行最前面显示“的提示符[root@www myapp]”是什么意思?

用SSH登陆Centos系统时&#xff0c;命令行最前面显示“的提示符[rootwww myapp]”是什么意思&#xff1f; 在SSH登录到CentOS系统时&#xff0c;提示符 [rootwww myapp] 中的 www 表示当前登录的主机名&#xff08;hostname&#xff09;&#xff0c;也就是指当前运行的CentOS系…

基于html+css的盒子展示2

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…