ThreadLocal是干嘛用的?

2023-05-16

ThreadLocal是通过将变量设置成Thread的局部变量,即使用该变量的线程提供一个独立的副本,可以独立修改,不会影响其他线程的副本,这样来解决多线程的并发问题。ThreadLocal主要是线程不安全的类在多线程中使用,一般常用于数据库连接和Session管理。看下ThreadLocal的官方注释:

{@code ThreadLocal} instances are typically private
* static fields in classes that wish to associate state with a thread (e.g.,
* a user ID or Transaction ID).//就是说ThreadLocal一般是作为private static变量来使用的,用于标记一个线程的一些状态

 

自己写的demo以及运行结果如下:

可以看出,打印出来的值是不一样的,这个是为什么?来分析下它的源码

 

点到ThreadLocal里面看了下,发现它是Thread类内部的一个属性:

/* ThreadLocal values pertaining to this thread. This map is maintained
 * by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;//本片主角

/*
 * InheritableThreadLocal values pertaining to this thread. This map is
 * maintained by the InheritableThreadLocal class.
 */
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;//使用它可以实现子线程可以获取父线程中的ThreadLocal变量 

 

来看下ThreadLocal的Set()方法:

这里getMap其实获取的就是上面的ThreadLocal.ThreadLocalMap threadLocals,然后讲ThreadLocal的引用设置进去。

 

再来看下它的get()方法

:

    也是获取到当前线程的ThreadLocalMap变量,然后讲当前ThreadLocal做为key,想要保存的值作为value设置到map中。

 

总结下个人理解:

    每个线程的内部都会有一个ThreadLocalMap的变量。当我们使用同一个ThreadLocal时,实际上每次都是往不同的map中设置值,只是这些map的key都是同一个。这样自然就不会有线程安全问题了,因为我们使用的是value,不是key!!!

    为什么要使用map是因为一个线程可以有不止一个的ThreadLocal变量。

 

同时也说明了一个问题,value是存在线程安全问题的:

看如下这个例子

public class ThreadLocalTest {
    private static ThreadLocal<List<Integer>> threadLocal = new ThreadLocal();
    private static List<Integer> list = new ArrayList<>();

    public static void main(String[] args) {
        list.add(0);
        threadLocal.set(list);
        System.out.println(threadLocal.get());

        for (int i = 0; i < 1; i++) {
            new Thread(new MyThread()).start();
        }

    }

    static class MyThread implements Runnable {
        @Override
        public void run() {
            threadLocal.set(list);
            System.out.println(threadLocal.get().get(0));
        }
    }

}

看下它的输出:

可以看到MyThread线程中获取到了主线程中的值,所以使用ThreadLocal时,每个线程对应的value得是不同的,不能是共享的变量!

 

 

ThreadLocal为什么会引发内存泄露问题:

    我们已经知道,ThreadLocal变量最终是设置到了Thread的ThreadLocalMap中。Key是ThreadLoacl变量的引用,Value是设置到ThreadLocal中的值。但是要注意的是,这个Key是一个弱引用:

 

为什么Key要设置成弱引用?来看下ThreadLocal内存结构图:

    个人理解是,当ThreadLocal被废弃时,可以回收掉当前ThreadLocalMap中的Key。这个时候,如果再有对这个ThreadLocal的操作,那么就会把原先的Value置为null,然后会在下一次GC的时候回收掉。

    但是,如果ThreadLocal引用变为null之后,不再对这个ThreadLocal变量进行操作了。那么就会由于Value这个强引用一直存在,一直都会有内存泄露的问题,个人理解这个就是ThreadLocal内存泄露的本质。

    所以,最好的办法就是ThreadLocal使用完毕之后,手动调用remove方法将其回收掉。

 

 

 

 

参考:

    https://www.zhihu.com/question/23089780(ThreadLocal和Synchroniezd区别)

    https://www.cnblogs.com/chenkeyu/p/7623653.html(ThreadLocal中放置Session)

    https://blog.csdn.net/tmr1016/article/details/100141446(ThreadLocal内存结构图)

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ThreadLocal是干嘛用的? 的相关文章

  • ThreadLocal是否会引起内存溢出?

    本文参考 xff1a 点击打开链接 最近碰到一个使用ThreadLocal时因为未调用remove 而险些引起内存溢出的问题 xff0c 所以看了下ThreadLocal的源码 xff0c 结合线程池原理做一个简单的分析 xff0c 确认是
  • Java ThreadLocal

    ThreadLocal是什么 xff1f 定义 xff1a 提供线程局部 变量 xff1b 一个线程局部边用在多个线程中分别有独立的值 xff08 副本 xff09 特点 xff1a 简单 xff08 开箱即用 xff09 快速 xff08
  • ThreadLocal类

    ThreadLocal类 什么是ThreadLocal为什么ThreadLocal是线程安全的呢 什么是ThreadLocal ThreadLocal可以简单的理解为他其实就是一个工具类 xff0c 用来存储线程局部变量的一个工具类 xff
  • ThreadLocal的深度解读

    一 J2SE的原始描述 This class provides thread local variables These variables differ from their normal counterparts in that eac
  • 深入理解ThreadLocal源码

    1 预备知识 强软弱虚引用 在Java中有四种引用的类型 强引用 软引用 弱引用 虚引用 设计这四种引用的目的是可以用程序员通过代码的方式来决定对象的生命周期 方便GC 强引用 强引用是程序代码中最广泛使用的引用 如下 Object o n
  • ThreadLocal,看我就够了!

    ThreadLocal 开胃菜 研究过Handler的应该对ThreadLocal比较眼熟的 线程中的Handler对象就是通过ThreadLocal来存放的 初识ThreadLocal的可能被它的名字有所误导 ThreadLocal初一看
  • 【Java】ThreadLocal详细解析

    ThreadLocal全面解析 前置知识 具有一定的javase和javaweb基础 熟悉synchronized关键字 熟悉HashMap 熟悉 JDBC技术 学习目标 了解ThreadLocal的介绍 掌握ThreadLocal的运用场
  • ThreadLocal详解

    如果有兴趣了解更多相关内容 欢迎来我的个人网站看看 瞳孔空间 一 基本介绍 ThreadLocal类能提供线程内部的局部变量 这种变量在多线程环境下访问时能保证各个线程的变量相对独立于其他线程内的变量 ThreadLocal实例通常来说都是
  • 将 Spring 应用程序上下文传递到与请求关联的 ThreadLocal 是否安全?

    在 JPA 中我想利用PrePersist带注释的方法来执行一些操作 而不是制作实现单例模式 使用 getInstance 等 所需的东西 我想知道是否通过 ThreadLocal 我在请求后关闭释放 传递 Spring Applicati
  • ThreadLocal - 用作带有 spring-boot 的 REST API 的上下文信息

    我有一些spring boot应用程序 它公开了 REST API 提到的 REST API 是由spring security 一切都很好 但是现在我需要设置上下文 用于服务请求 设置上下文是指根据用户上下文选择数据源 关键是Routin
  • 使用 ThreadLocal 作为数据上下文是个好主意吗?

    使用 ThreadLocal 作为 Web 应用程序中数据的上下文是个好主意吗 这就是它的目的 但请注意删除上下文末尾的 ThreadLocal 否则可能会出现内存泄漏 或者至少会保留未使用的数据太长时间 ThreadLocals 也非常快
  • EJB 容器中的 ThreadLocal(和 Singleton)

    我编写了一个授权系统 它依赖于代表当前用户的对象 为了简化编程并提高性能 我想在用户登录后将这些对象保存在 ThreadLocal 中 它看起来像这样 public class UserCache private static final
  • SecurityContextHolder 提供错误的用户详细信息

    在我的应用程序中 我们正在捕获每笔交易的用户详细信息SecurityContextHolder认证对象 但它给出了错误UserID它似乎 以下是代码片段供您参考 安全上下文 xml 弹簧安全 3 2
  • Spring安全策略MODE_INHERITABLETHREADLOCAL。为什么?

    我了解当我们在 Spring 安全策略中使用 MODE THREADLOCAL 和 MODE INHERITABLETHREADLOCAL 时如何以及会发生什么 我不明白的是 为什么有人会使用 MODE THREADLOCAL 而不是 MO
  • 如何从 Java servlet Web 容器正确实现 RabbitMQ RPC?

    我希望传入的 Java servlet Web 请求使用 RPC 方法调用 RabbitMQ 如上所述here http www rabbitmq com tutorials tutorial six java html 但是 我不确定如何
  • C++11:重要的线程局部静态变量?

    我有一个X类 class X 我想做这个 void f thread local static X x 实际上我使用的是 gcc 所以关键字是 thread 但我不能 因为你只能有微不足道的 thread locals 对此最好的解决方法是
  • 我应该何时以及如何使用 ThreadLocal 变量?

    我什么时候应该使用ThreadLocal https docs oracle com javase 8 docs api java lang ThreadLocal html多变的 它是如何使用的 一种可能 也是常见 的用途是当您有一些非线
  • 为什么 ThreadLocal 实用程序在 Spring MVC 应用程序中总是返回 null?

    我编写了这个实用程序类来在 Spring MVC 应用程序中保存临时数据 public abstract class FooUtil private static final ThreadLocal
  • thread_local成员变量构造

    我遇到了 thread local 的一些奇怪行为 不确定我是否做错了什么或者这是一个 GCC 错误 我有以下最小重现场景 include
  • 将 ThreadLocal 与 ExecutorService 一起使用是否危险?

    我在下面的博客上介绍了 ThreadLocals 的概念 https www baeldung com java threadlocal https www baeldung com java threadlocal 它说 不要将 Thre

随机推荐

  • SpringBoot实现多线程

    原文链接 代码地址 xff1a https github com Snowstorm0 learn async 1 线程同步和异步 线程同步 xff1a A线程要请求某个资源 xff0c 但是此资源正在被B线程使用中 xff0c 因为同步机
  • pip安装报错:UnicodeDecodeError ‘utf-8‘ codec can‘t decode byte 0xc3 in position 4

    原文链接 使用pip命令安装模块时 xff0c 若出现报错 xff1a UnicodeDecodeError utf 8 codec can t decode byte 0xc3 in position 4 invalid continua
  • Prometheus的使用

    原文链接 Prometheus 是一个开放性的监控解决方案 xff0c 用户可以非常方便的安装和使用 Prometheus 并且能够非常方便的对其进行扩展 在Prometheus的架构设计中 xff0c Prometheus Server
  • Java中restTemplate携带Header请求

    原文链接 RestTemplate是Spring提供的用于发送HTTP请求的客户端工具 现在我们要在Java中使restTemplate携带Header请求 创建请求 创建请求头 xff1a span class token class n
  • SpringBoot整合ElasticSearch

    原文链接 ElasticSearch是个开源分布式搜索引擎 xff0c 提供搜集 分析 存储数据三大功能 它的特点有 xff1a 分布式 xff0c 零配置 xff0c 自动发现 xff0c 索引自动分片 xff0c 索引副本机制 xff0
  • Python将二维数组输出为图片

    原文链接 使用Python读取二维数组 xff0c 将二维数组输出为图片 xff0c 并保存在本地 代码如下 xff1a span class token comment coding 61 utf8 span span class tok
  • 如何使用Tin快速搭建Gitlab-ce?(史上最简单方法)

    GitLab是Git代码版本管理平台 xff0c 相比于GitHub xff0c GitLab还免费支持私人仓库 GitLab ce是gitlab的开源版本 目前网上Gitlab ce的安装方法有很多 xff0c 但大同小异都需要安装各种依
  • 堆叠降噪自动编码器 Stacked Denoising Auto Encoder(SDAE)

    原文链接 自动编码器 xff08 Auto Encoder xff0c AE xff09 自动编码器 xff08 Auto Encoder xff0c AE xff09 自编码器 xff08 autoencoder xff09 是神经网络的
  • PyTorch中 nn.Conv2d与nn.ConvTranspose2d函数的用法

    原文链接 1 通道数问题 xff1a 描述一个像素点 xff0c 如果是灰度 xff0c 那么只需要一个数值来描述它 xff0c 就是单通道 如果有RGB三种颜色来描述它 xff0c 就是三通道 最初输入的图片样本的 channels xf
  • Python中LSTM回归神经网络的时间序列预测

    原文链接 这个问题是国际航空乘客预测问题 xff0c 数据是1949年1月到1960年12月国际航空公司每个月的乘客数量 xff08 单位 xff1a 千人 xff09 xff0c 共有12年144个月的数据 网盘链接 提取码 xff1a
  • pip安装时 fatal error C1083: 无法打开包括文件: “io.h”: No such file or directory

    原文链接 使用pip安装模块 xff0c 出现错误 xff1a c users anaconda3 include pyconfig h 68 fatal error C1083 无法打开包括文件 io h No such file or
  • linux 程序被Killed,查看原因

    原文链接 1 查看信息 xff1a 输入以下程序 xff1a dmesg egrep i B100 39 killed process 39 可以输出最近killed的信息 2 设定kill优先度 xff1a xff08 1 xff09 完
  • Kafka的幂等性与事务性理解

    最近在深入理解Flink的Exactly Once xff0c 发现Flink Checkpoint只能保障Flink程序内部的一致性 xff0c 无法保证Sink到外部系统的Exactly Once语义 但是Sink到外部如果实现了Two
  • 为什么不直接操作State,而是要额外定义一个变量

    最近浏览Flink文章的时候发现一个现象 xff0c 就是在操作State的时候 xff0c 很多文章里面并不会直接操作State xff0c 而是会定义一个相似的变量去操作 xff0c 在 snapshot 和 recover 的时候讲变
  • 了解下SparkSQL中的笛卡尔积

    虽然应该尽量避免使用笛卡尔积 xff0c 因为要全量匹配 xff0c 所以运算的效率十分低下 xff0c 但是有些业务有必须得用 xff0c 所以在此了解下SparkSQL中的笛卡尔积 SparkSQL中计算笛卡尔积时有两种Join方式 x
  • 在Redis集群模式下使用pipeline进行批量操作

    最近开始又接触到了Redis xff0c 之前在工作中使用Redis的时候 xff0c 由于QPS不高 xff0c 都是直接get set搞定了 这次遇到的业务数据量比较大 xff0c 更新也很频繁 xff0c Redis使用是集群模式 x
  • RDD计算时是把数据全部加载至内存么

    RDD的本质 RDD的本质是一个函数 而RDD的变换不过是函数的嵌套 RDD有两类 输入的RDD 典型如KafkaRDD JdbcRDD转换的RDD 如MapPartitionsRDD RDD的处理流程 以如下代码为例 sc textFil
  • mysql中limit用法详解

    Mysql中limit的用法详解 在我们使用查询语句的时候 xff0c 经常要返回前几条或者中间某几行数据 xff0c 这个时候怎么办呢 xff1f 不用担心 xff0c mysql 已经为我们提供了这样一个功能 xff0c 尽管语法逻辑很
  • 练习代码遇到的零碎知识

    一 xff0c c 43 43 中使用malloc 时 xff0c 出现error malloc was not declared in this scope 1 书写错误 2 没有引用相应的库 解决方法 xff1a 引入stdlib h库
  • ThreadLocal是干嘛用的?

    ThreadLocal是通过将变量设置成Thread的局部变量 xff0c 即使用该变量的线程提供一个独立的副本 xff0c 可以独立修改 xff0c 不会影响其他线程的副本 xff0c 这样来解决多线程的并发问题 ThreadLocal主