09. Java ThreadLocal 的使用

news2024/11/16 3:52:17

1. 前言

本节内容主要是对 ThreadLocal 进行深入的讲解,具体内容点如下:

  • 了解 ThreadLocal 的诞生,以及总体概括,是学习本节知识的基础;
  • 了解 ThreadLocal 的作用,从整体层面理解 ThreadLocal 的程序作用,为本节的次重点;
  • 掌握 ThreadLocal set 方法的使用,为本节重点内容;
  • 掌握 ThreadLocal get 方法的使用,为本节重点内容;
  • 掌握 ThreadLocal remove 方法的使用,为本节重点内容;
  • 掌握多线程下的 ThreadLocal 的使用,为本节内容的核心。

2. ThreadLocal 概述

诞生:早在 JDK 1.2 的版本中就提供 java.lang.ThreadLocal,ThreadLocal 为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。

概述:ThreadLocal 很容易让人望文生义,想当然地认为是一个 “本地线程”。其实,ThreadLocal 并不是一个 Thread,而是 Thread 的局部变量,也许把它命名为 ThreadLocalVariable 更容易让人理解一些。

当使用 ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

总体概括:从线程的角度看,目标变量就象是线程的本地变量,这也是类名中 “Local” 所要表达的意思。

了解完 ThreadLocal 的总体介绍后,对其有了一个总体的了解,那我们接下来继续探究 ThreadLocal 的真实面貌以及使用。

3. ThreadLocal 的作用

作用:ThreadLocal 是 JDK 包提供的,它提供了线程本地变量,也就是如果你创建了一个 ThreadLocal 变量,那么访问这个变量的每个线程都会有这个变量的一个本地副本。当多个线程操作这个变量时,实际操作的是自己本地内存里面的变量,从而避免了线程安全问题。

ThreadLocal 是线程本地存储,在每个线程中都创建了一个 ThreadLocalMap 对象,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。通过这种方式,避免资源在多线程间共享。

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

4. ThreadLocal set 方法

方法介绍:set 方法是为了设置 ThreadLocal 变量,设置成功后,该变量只能够被当前线程访问,其他线程不可直接访问操作改变量。

实例

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

Tips:set 方法可以设置任何类型的值,无论是 String 类型 ,Integer 类型,Object 等类型,原因在于 set 方法的 JDK 源码实现是基于泛型的实现,此处只是拿 String 类型进行的举例。

实例

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);
    }

5. ThreadLocal get 方法

方法介绍:get 方法是为了获取 ThreadLocal 变量的值,get 方法没有任何入参,直接调用即可获取。

实例

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

结果验证

Hello World

探究:请看如下程序,并给出输出结果

实例

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。

结果验证

World is beautiful
World is beautiful

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

6. ThreadLocal remove 方法

方法介绍:remove 方法是为了清除 ThreadLocal 变量,清除成功后,该 ThreadLocal 中没有变量值。

实例

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 方法会直接清除这个变量值。

结果验证

Hello World
null

7. 多线程下的 ThreadLocal

对 ThreadLocal 的常用方法我们已经进行了详细的讲解,那么多线程下的 ThreadLocal 才是它存在的真实意义,那么问了更好的学习多线程下的 ThreadLocal,我们来进行场景的创建,通过场景进行代码实验,更好的体会并掌握 ThreadLocal 的使用。

场景设计

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

结果预期:在 threadOne 设置成功后进入了 5000 毫秒的休眠状态,此时由于只有 threadTwo 调用了 remove 方法,不会影响 threadOne 的 get 方法打印,这体现了 ThreadLocal 变量的最显著特性,线程私有操作。

实例

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

        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                local.set("threadOne's local value");
                try {
                    Thread.sleep(5000); //沉睡5000 毫秒,确保 threadTwo 执行 remove 完成
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(local.get());
            }
        });
        Thread threadTwo = new Thread(new Runnable() {
            @Override
            public void run() {
                local.set("threadTwo's local value");
                System.out.println(local.get());
                local.remove();
                System.out.println("local 变量执行 remove 操作完毕。");
            }
        });
        threadTwo. start();
        threadOne. start();
    }
}

结果验证

threadTwo's local value
local 变量执行 remove 操作完毕。
threadOne's local value

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

8. 小结

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

本节的重中之重是掌握 ThreadLocal 的方法使用以及其特点,核心内容为多线程下的 ThreadLocal 的使用。

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

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

相关文章

VC++开发积累——vc++6.0中删除函数的方法,右键,Delete

目录 引出插曲&#xff1a;删除函数的方法多行注释的实现代码输入的自动提示搜索出来&#xff0c;标记和取消标记跳转到上一步的位置 ctrl TAB 总结其他规范和帮助文档创建第一个Qt程序对象树概念信号signal槽slot自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自…

千呼新零售2.0-OCR拍照识别采购单

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物、中医养生、大健康等连锁店…

Python 实现Excel转TXT,或TXT文本导入Excel

Excel是一种具有强大的数据处理和图表制作功能的电子表格文件&#xff0c;而TXT则是一种简单通用、易于编辑的纯文本文件。将Excel转换为TXT可以帮助我们将复杂的数据表格以文本的形式保存&#xff0c;方便其他程序读取和处理。而将TXT转换为Excel则可以将文本文件中的数据导入…

AI引领创意潮流:高效生成图片,参考图助力,一键保存到指定文件夹

在这个数字与创意交融的时代&#xff0c;我们迎来了AI绘画的新纪元。借助先进的AI技术&#xff0c;我们不仅能够高效生成图片&#xff0c;还能在参考图的启发下&#xff0c;激发无限创意&#xff0c;让您的想象力在数字世界中自由翱翔。 首助编辑高手软件中的魔法智能绘图板块&…

PMP证书在国内已经泛滥了,大家怎么看?

目前&#xff0c;越来越多的人获得了PMP证书。自1999年PMP引入中国以来&#xff0c;全国累计PMP考试人数接近60万人次&#xff0c;通过PMP认证的人数约为42万人。虽然这个数据看起来很大&#xff0c;但绝对不能说是过多。 首先&#xff0c;PMP在中国并不普遍。根据美国项目管理…

解决go语言对接s3的SDK上传文件遇到的问题

先看正确的配置 问题1 配置文件中的OssEndpoint 不管是minio还是oss需要带上http://或者https:// 否则会出现这个问题 operation error S3: PutObject, exceeded maximum number of attempts, 3, https response error StatusCode: 0, RequestID: , HostID: , request send …

qt报错:“QtRunWork”任务返回了 false,但未记录错误。

qt报错&#xff1a;“QtRunWork”任务返回了 false&#xff0c;但未记录错误。 说明情况一 说明 这个报错可能的原因有很多&#xff0c;这里只写一种&#xff0c;以后遇到再进行补充。 情况一 如果 Q_OBJECT 宏未正确处理&#xff0c;通常会出现类似的错误。 要使用信号与槽…

视频汇聚平台LntonCVS视频集中存储平台技术解决方案

安防视频监控技术是一种利用各种监控设备捕捉实时画面&#xff0c;并将其传输至监控中心或数据存储设备的技术。随着科技的不断进步&#xff0c;监控视频技术也在不断改进&#xff0c;应用领域也在不断扩展。 然而&#xff0c;尽管技术进步&#xff0c;当前视频监控技术仍然面临…

PointCloudLib-特征(Features)-全局对齐空间分布 (GASD) 描述符

全局对齐空间分布 (GASD) 描述符 本文档介绍用于高效对象识别和姿势估计的全局对齐空间分布 ([GASD]) 全局描述符。 GASD 基于对表示对象实例的整个点云的参考系的估计,该参考系用于将其与规范坐标系对齐。之后,根据对齐点云的 3D 点的空间分布方式计算对齐点云的描述符…

最新!计算机类SCI期刊全名单!你想发的顶刊都在这里

【SciencePub学术】近日&#xff0c;2023JCR正式发布&#xff0c;最受瞩目就是各类期刊的最新影响因子排名&#xff0c;本期&#xff0c;小编对计算机类的期刊做了一个整理&#xff0c;供计算机方向的研究学者们参考&#xff01; 来源&#xff1a;WOS数据库官网 完整名单 ※ 本…

新手选择代理IP时这几点误区一定要避开!

在选择代理IP时&#xff0c;许多用户可能会因为对代理IP的认识不足或受到一些误导&#xff0c;而陷入一些常见的误区。这些误区不仅可能导致用户无法达到预期的效果&#xff0c;还可能带来一些不必要的风险。下面&#xff0c;IPIDEA代理IP就与大家一同分析在选择代理IP时需要避…

《Attention is all you need》通俗解读,彻底理解版:part1

最近在更新 Transformer 的技术专栏&#xff0c;如果你关注我的公众号的话&#xff0c;会发现有不少文章都打上了“Transformer最后一公里”的标签。 打上标签的文章要么是介绍 Transformer 技术的&#xff0c;要么是介绍学习Transformer 所需要的背景知识的&#xff0c;比如这…

typescript学习回顾(二)

今天来分享一下ts的基础&#xff0c;如何使用ts&#xff0c;以及ts具体的作用&#xff0c;如何去约束我们开发中常见的一些数据的&#xff0c;最后做一个小练习来巩固对ts基础的掌握程度。 类型约束 如何加类型约束呢 变量、函数的参数、函数的返回值位置加上:类型 比如 //约…

AI绘画Stable diffusion的SDXL模型超详细讲解,针不错!(含实操教程)

大家好&#xff0c;我是画画的小强 朋友们好&#xff0c;今天分享的是Stable diffusion的SDXL模型以及相关实操。 与之前的SD1.5大模型不同&#xff0c;这次的SDXL在架构上采用了“两步走”的生图方式&#xff1a; 以往SD1.5大模型&#xff0c;生成步骤为 Prompt → Base → …

时序分析(二):input delay分析

一、IO接口分析基本模型 数据按照同步方式可分为系统同步和源同步方式两种。所谓系统同步指发送端和接收端共用一个时钟源&#xff1b;源同步指发送端提供数据同步时钟&#xff0c;接收端根据该时钟进行数据接收。现在多数通信中使用源同步方式&#xff0c;例如以太网、ADC等。…

使用 C# 实现Windows桌面壁纸软件

一、设置Windows壁纸 将电脑上的图片设置为壁纸&#xff0c;代码如下&#xff1a; [DllImport("user32.dll", CharSet CharSet.Auto)] static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); const int SPI_SETDESKW…

DM达梦数据库分析函数整理

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

从用户到粉丝,再到“裂变客户”:品牌忠诚度如何升级?

在竞争激烈的商业环境中&#xff0c;品牌忠诚度对于企业的成功至关重要。然而&#xff0c;如何将普通用户转化为忠实粉丝&#xff0c;并进一步升级为“裂变客户”&#xff0c;是每一个品牌都需要深思的问题。 从用户转变为粉丝&#xff0c;品牌需要建立与用户的情感连接 这不…

维吉尼亚密文解密小程序

维吉尼亚密文解密小程序 这几天在看CTF相关的课程&#xff0c;涉及到古典密码学和近代密码学还有现代密码学。自己编了一个解密小程序。 Vigenere 维吉尼亚密码 维吉尼亚是多表替换密码中比较典型的代表&#xff0c;维吉尼亚密码是在凯撒密码基础上产生的一种加密方法&#…

床上用品跨境电商:拥有沃尔玛1P特权的商家享有哪些显著优势?

在全球化的背景下&#xff0c;跨境电商对床上用品行业至关重要。沃尔玛因其品牌影响力、客户资源及物流体系在跨境电商平台中脱颖而出。拥有沃尔玛1P特权的商家享有更多曝光机会和独家优惠。那么&#xff0c;这些特权商家具体有哪些优势呢? 沃尔玛1P特权商家在曝光率上具有显著…