Java并发-ThreadLocal的使用

news2025/2/26 20:09:45

ThreadLocal 概述

  • 当使用 ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
  • 当多个线程操作这个变量时,实际操作的是自己本地内存里面的变量,从而避免了线程安全问题。
  •  ThreadLocal 是线程本地存储,在每个线程中都创建了一个 ThreadLocalMap 对象,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。通过这种方式,避免资源在多线程间共享。

使用场景:如为每个线程分配一个 JDBC 连接 Connection。这样就可以保证每个线程的都在各自的 Connection 上进行数据库的操作,不会出现 A 线程关了 B 线程正在使用的 Connection。还有 Session 管理等问题

set方法

ThreadLocal为每个线程都创建一个map对象。从而保证线程隔离。

public void set(T value) { // T value , 泛型实现,可以 set 任何对象类型
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

get方法

看这个方法,我们能够想到如果是map时,get 的两次结果应该是"Hello World" 和"World is beautiful".但结果却是。。。。

public class DemoTest{
    public static void main(String[] args){
        ThreadLocal<String> localVariable = new ThreadLocal<> () ;
        localVariable.set("Hello World");
        localVariable.set("World is beautiful");
        System.out.println(localVariable.get());
        System.out.println(localVariable.get());
    }
}

 

探究解析:从程序中来看,我们进行了两次 set 方法的使用。

第一次 set 的值为 Hello World ;第二次 set 的值为 World is beautiful。接下来我们进行了两次打印输出 get 方法,那么这两次打印输出的结果都会是 World is beautiful。 原因在于第二次 set 的值覆盖了第一次 set 的值,所以只能 get 到 World is beautiful。

总结:ThreadLocal 中只能设置一个变量值,因为多次 set 变量的值会覆盖前一次 set 的值,我们之前提出过,ThreadLocal 其实是使用 ThreadLocalMap 进行的 value 存储,那么多次设置会覆盖之前的 value,这是 get 方法无需入参的原因,因为只有一个变量值。

remove方法

public class DemoTest{
    public static void main(String[] args){
        ThreadLocal<String> localVariable = new ThreadLocal<> () ;
        localVariable.set("Hello World");
        System.out.println(localVariable.get());
        localVariable.remove();
        System.out.println(localVariable.get());
    }
}

Tips:remove 方法同 get 方法一样,是没有任何入参的,因为 ThreadLocal 中只能存储一个变量值,那么 remove 方法会直接清除这个变量值

上面代码运行的结果,如下图所示。 

 

多线程下的 ThreadLocal

 

场景设计

  • 创建一个全局的静态 ThreadLocal 变量,存储 String 类型变量;
  • 创建两个线程,分别为 threadOne 和 threadTwo;
  • threadOne 进行 set 方法设置,设置完成后沉睡 5000 毫秒,苏醒后进行 get 方法打印;
  • threadTwo 进行 set 方法设置,设置完成后直接 get 方法打印,打印完成后调用 remove 方法,并打印 remove 方法调用完毕语句;
  • 开启线程 threadOne 和 threadTwo ;
  • 执行程序,并观察打印结果。
package jvm.juc;

public class ThreadLocalTest {
    static ThreadLocal<String> local = new ThreadLocal<>();
    public static void main(String[] args) {

        Thread threadA = new Thread(()->{
            local.set("线程One-在里面设置值了");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(local.get());
        });
        threadA.setName("ThreadOne");


        Thread threadB = new Thread(()->{
            local.set("线程Two-在里面设置值了");
            System.out.println(local.get());
            local.remove();
        });
        threadB.setName("ThreadTwo");

        threadA.start();
        threadB.start();
    }
}

从以上结果来看,在 threadTwo 执行完 remove 方法后,threadOne 仍然能够成功打印,这更加证明了 ThreadLocal 的专属特性,线程独有数据,其他线程不可侵犯。
 

总结

ThreadLocal 是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal 比直接使用 synchronized 同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性,但也有缺点是只能存储一个值。

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

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

相关文章

python实现熵权法

原文&#xff1a;https://mp.weixin.qq.com/s/vPNPdbZy11q1qsfEz9etZQ 1 熵权法简介 熵源自于希腊语 “ 变化 ” 表示变化的容量&#xff0c;德国物理学家克劳修斯为了将热力学第二定律格式化而引入熵的概念 。 熵的概念来源于热力学&#xff0c;是用来描述过程的不可逆现象…

sql注入手法详解

sql定义 sql--结构化查询语句 sql注入&#xff1a;首先我们通过前端将我们的payload(恶意代码)传送到后台服务器 传送到后台以后 我们提交的payload拼接到sql语句中 作为sql语句的一部分被执行 从而导致数据库又被脱库甚至删库的风险 使得数据库受损 sql注入手法 sql注入可…

领悟《信号与系统》之 非周期信号的傅里叶变换及性质

非周期信号的傅里叶变换及性质一、非周期信号的傅里叶变换二、 典型信号的傅立叶变换1.单边指数信号2.偶双边指数3. 矩阵脉冲信号4. 奇双边指数5. 符号函数6. 冲激信号7. 阶跃信号三、常用傅里叶变换表这里记录的信号都是非周期信号的傅里叶变化&#xff0c;频谱变换的特点就是…

VsCode 配置eslint,支持typescript的语法检查,及时发现低级语法错误,包括函数未定义等行为

背景 最近学习cocos的小游戏制作&#xff0c;参考游戏管理器的代码进行调试的时候&#xff0c;发现自己运行的结果一直都是跟官方效果不一样&#xff0c;没有自动生成更多的方块。肉眼检查代码差异&#xff0c;基本上代码是一样的&#xff0c;浏览器页面调试的时候也看不出问题…

[附源码]Python计算机毕业设计高校教室申请管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【仿牛客网笔记】项目进阶,构建安全高效的企业服务——热帖排行

p:投票数 T&#xff1a;发布时间间隔 G&#xff1a;系数&#xff0c;通常为1.5,1.8 计算帖子的分数 注入RedisTemplate 帖子刷新 实现定时任务 刷新帖子 实现更新帖子分数 刷新帖子分数任务 配置Trigger 注释掉定时任务&#xff0c;注释注解就可以 启动服务之…

人口数据集:地级市常住人口与户籍人口、人口1%抽样调查数据两大维度指标数据

一、地级市常住人口与户籍人口 1、数据来源&#xff1a;地级市常住人口数据&#xff08;主要来源于各地政府公报&#xff09;&#xff0c;户籍人口数据来源于《中国城市统计年鉴》 2、时间跨度&#xff1a;2003-2019年 3、区域范围&#xff1a;280个地级市 4、指标说明&…

[附源码]Python计算机毕业设计电影网站系统设计

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【Spring】Bean生命周期

一、背景&#xff1a; 自动注入 UserService 对象&#xff0c; UserService 结构如下 二、创建 Bean 的整体流程&#xff1a; UserService.class ------> 无参的构造方法 ------> 普通对象&#xff08;无值&#xff09; ------> 依赖注入 ------> 初始化前&#…

FreeCAD二次开发-基于控制台模式FC外部开发

版本 FreeCAD0.18.2+PyCharm Community 2020.3.3 演示效果 环境搭建步骤 1.先安装好FreeCAD和PyCharm 2.添加环境变量 点击确定,全部关掉。 3.测试变量是否生效(CMD打开控制台,输入python回车) 弹出如下,说明可以进入FreeCAD自带的python解释器 4.打开PyCharm新建项目 …

Windows静态库用C++代码调用C语言的旧库方法extern ”c“

静态库特点 运行不存在 静态库源码被链接到调用程序中 目标程序的归档 C语言静态库 C静态库的创建 1.创建一个静态库项目 2.添加库程序&#xff0c;源文件使用C文件 C静态库的使用 库路径设置&#xff1a;可以使用pragma关键字设置 #pragma comment&#xff08;lib,“./lib/cli…

15、Mybatis获取参数值的情况1(mapper接口方法的参数为单个字面量类型)

Mybatis获取参数值的情况1&#xff08;mapper接口方法的参数为单个字面量类型&#xff09; #{}和${}可以通过任意名称来获取 mapper接口方法的参数为单个字面量类型第一步&#xff1a; 第二步&#xff1a;#{} 结果&#xff1a; 第二步:${} 结果 第三步&#xff1a; 这种也行&…

站酷基于服务网格 ASM 的生产实践

01背景介绍Aliware站酷&#xff08;ZCOOL&#xff09;2006 年 8 月创立于北京&#xff0c;深耕设计领域多年&#xff0c;聚集了 1500 万设计师、摄影师、插画师、艺术家、创意人&#xff0c;在设计创意群体中具有一定的影响力与号召力。站酷在创立之初&#xff0c;就以“让设计…

libcurl 库的编译

因为要用到 libcurl 库的接口进行练习&#xff0c;而现在手上只有curl相关的头文件&#xff0c;那没办法只能下载源码进行编译了&#xff0c;这里记录一下编译 x86 与 hisi dv300 版本的动态库。 根据头文件 curlver.h 里的版本信息&#xff0c;我是直接下载 7.67.0 版本的源码…

领悟《信号与系统》之 LTI 系统的卷积积分及性质

LTI 系统的卷积积分及性质一、卷积积分及其性质1. 任意信号的分解2. 任意信号作用下的零状态响应3. 卷积的定义4. 卷积性质1. 代数性质2. f(t)与奇异信号的卷积 &#xff08;非常重要&#xff09;3. 卷积的微分和积分4. 卷积时移5. 常用信号的卷积公式二、总结重点笔记主要记录…

MNN--初步学习

来自阿里MNN有三个贡献点&#xff1a; 提出了预推理机制&#xff0c;在线计算推理成本和最优方案优化了kernel提出后端抽象实现混合调度MNN的架构&#xff1a; 分离线和在线两部分。离线就是很传统的模型转换、优化、压缩、量化的那一套东西&#xff0c;这里mnn转出的模型文件…

【外卖项目实战开发三】

文章目录分类管理业务开发公共字段自动填充问题分析代码实现功能完善新增分类需求分析数据模型代码开发分类信息分页查询需求分析代码开发删除分类需求分析代码开发代码完善关键代码修改分类需求分析代码实现分类管理业务开发 公共字段自动填充 问题分析 前面我们已经完成了…

A股上市公司MSCI指数和ESG评级效果(2010-2021年)

1、数据来源&#xff1a;摩根斯坦利资本国际公司(Morgan Stanley Capital International) 2、时间跨度&#xff1a;2010--2021 3、区域范围&#xff1a;A股上市公司 4、指标说明&#xff1a; ESG是英文Environmental&#xff08;环境&#xff09;、Social&#xff08;社会&…

《人月神话》(The Mythical Man-Month)6贯彻执行(Passing the Word)

《人月神话》&#xff08;The Mythical Man-Month&#xff09;Chapter 6. 贯彻执行 Passing the Word他只是坐在那里&#xff0c;嘴里说&#xff1a;"做这个&#xff01;做那个&#xff01;"当然&#xff0c;什么都不会发生&#xff0c;光说不做是没有用的。- 哈里杜…

基于主从博弈的社区综合能源系统分布式协同优化运行策略matlab/cplex程序

基于主从博弈的社区综合能源系统分布式协同优化运行策略matlab/cplex程序 随着能源市场由传统的垂直一体式结构向交互竞争型 结构转变&#xff0c;社区综合能源系统的分布式特征愈发明显&#xff0c;传统 的集中优化方法难以揭示多主体间的交互行为。该文提出一 种基于主从博弈…