子线程无法访问父线程中通过ThreadLocal设置的变量

引出结论

学习过ThreadLocal的童鞋都知道,在子线程中,是无法访问父线程通过ThreadLocal设置的变量的。

package thread;/*** @author heyunlin* @version 1.0*/
public class ThreadLocalExample {public static void main(String[] args) throws InterruptedException, NoSuchFieldException, IllegalAccessException {ThreadLocal<String> threadLocal = new ThreadLocal<>();threadLocal.set("hello");Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("run()...");/** 子线程中无法访问父线程中设置的ThreadLocal变量*/System.out.println(threadLocal.get());}});thread.start();thread.join();System.out.println(thread);System.out.println(threadLocal.get());}}

运行结果:

InheritableThreadLocal就是为了解决这个不可见问题而生的~

package thread;/*** @author heyunlin* @version 1.0*/
public class InheritableThreadLocalExample {public static void main(String[] args) throws InterruptedException, NoSuchFieldException, IllegalAccessException {InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();threadLocal.set("hello");Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("run()...");System.out.println(threadLocal.get());}});thread.start();thread.join();System.out.println(thread);System.out.println(threadLocal.get());}}

运行结果:

 

分析原因

那么, 究竟是什么原因导致的子线程无法访问父线程中的ThreadLocal变量呢,接下来研究ThreadLocal这个类的源码。

先看一下这个ThreadLocal类上的文档注释,大概了解ThreadLocal是用来干什么的

/*** This class provides thread-local variables.  These variables differ from* their normal counterparts in that each thread that accesses one (via its* {@code get} or {@code set} method) has its own, independently initialized* copy of the variable.  {@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).** <p>For example, the class below generates unique identifiers local to each* thread.* A thread's id is assigned the first time it invokes {@code ThreadId.get()}* and remains unchanged on subsequent calls.* <pre>* import java.util.concurrent.atomic.AtomicInteger;** public class ThreadId {*     // Atomic integer containing the next thread ID to be assigned*     private static final AtomicInteger nextId = new AtomicInteger(0);**     // Thread local variable containing each thread's ID*     private static final ThreadLocal&lt;Integer&gt; threadId =*         new ThreadLocal&lt;Integer&gt;() {*             &#64;Override protected Integer initialValue() {*                 return nextId.getAndIncrement();*         }*     };**     // Returns the current thread's unique ID, assigning it if necessary*     public static int get() {*         return threadId.get();*     }* }* </pre>* <p>Each thread holds an implicit reference to its copy of a thread-local* variable as long as the thread is alive and the {@code ThreadLocal}* instance is accessible; after a thread goes away, all of its copies of* thread-local instances are subject to garbage collection (unless other* references to these copies exist).** @author  Josh Bloch and Doug Lea* @since   1.2*/

关键注释

博主在类的文档注释上提取了几个关于ThreadLocal的重要的说明

This class provides thread-local variables. 

这个类提供了线程本地变量

ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread. 

ThreadLocal实例提供了可以关联一个线程的静态字段。

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

只要线程是存活状态,并且ThreadLocal对象可以访问,每个线程都拥有一个线程本地变量的副本的引用;

在线程执行完方法之后,所有线程本地变量都会被gc(垃圾收集器)回收,除非有其他变量引用了它。

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

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

相关文章

21.Happens-Before原则

文章目录 Happens-Before原则1.Happens-Before规则介绍2.规格介绍2.1.顺序性规则(as-if-serial)2.2.volatile规则2.3.传递性规则2.4.监视锁规则2.5.start规则2.6.join()规则 Happens-Before原则 JVM内存屏障指令对Java开发工程师是透明的&#xff0c;是JMM对JVM实现的一种规范和…

SpringBoot使用rsa-encrypt-body-spring-boot实现接口加解密

废话不多说&#xff0c;直接上代码 引入依赖 <dependency><groupId>cn.shuibo</groupId><artifactId>rsa-encrypt-body-spring-boot</artifactId><version>1.0.1.RELEASE</version> </dependency>配置文件 rsa:encrypt:# 是…

Leetcode 剑指 Offer II 079.子集

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返…

开发一个电商系统的技术选型:前端、后端、数据分析与AI分析

随着电子商务的蓬勃发展&#xff0c;开发一个功能强大、用户友好的电商系统成为许多企业的首要任务。在这个过程中&#xff0c;技术选型至关重要&#xff0c;因为它直接影响系统的性能、可扩展性和用户体验。本文将讨论开发电商系统时在前端、后端、数据分析和AI分析方面的技术…

`TCP_KEEPIDLE`、`TCP_KEEPINTVL` 和 `TCP_KEEPCNT` 是 TCP 套接字选项,用于控制 TCP 连接的保活机制

TCP_KEEPIDLE、TCP_KEEPINTVL 和 TCP_KEEPCNT 是 TCP 套接字选项&#xff0c;用于控制 TCP 连接的保活机制。这些选项通常用于在长时间空闲的连接中检测对端是否存活&#xff0c;并在必要时终止连接。 TCP_KEEPIDLE&#xff1a;指定开始发送 TCP KeepAlive 消息之前&#xff0c…

系统升级中,请稍后...Time: 2024-05-26 10:59:46 Code:OE.20001

没错&#xff01;你能看到“系统升级中&#xff0c;请稍后…Time: 2024-05-26 10:59:46 Code:OE.20001”这个提示你找到这里就对了&#xff01;以上提示是婚恋交由系统奥壹的oelove的报错内容&#xff01;为什么报错&#xff1f;那说明你不是商业用户&#xff0c;默认程序是需要…

【spring】@PathVariable注解学习

PathVariable介绍 PathVariable是Spring框架中的一个注解&#xff0c;主要用于处理RESTful风格URL中的路径变量。在RESTful接口设计中&#xff0c;我们经常将资源的ID或者其他标识信息直接放在URL路径中&#xff0c;而不是作为查询参数。PathVariable注解使得控制器方法能够轻…

FreeRTOS_同步互斥与通信_队列集_学习笔记

FreeRTOS_同步互斥与通信_环形buffer、队列_学习笔记 5.5 队列集 要支持多个输入设备时&#xff0c;我们需要实现一个“InputTask”&#xff0c;它读取各个设备的队列&#xff0c;得到数据后再分别转换为游戏的控制键。 InputTask如何及时读取到多个队列的数据&#xff1f;要…

C#的奇技淫巧:利用WinRM来远程操控其他服务器上的进程

前言&#xff1a;有时候远程服务器的进程你想偷偷去围观一下有哪些&#xff0c;或者对一些比较调皮的进程进行封杀&#xff0c;或者对一些自己研发的服务进行远程手动启动或者重启等&#xff0c;又不想打开远程桌面&#xff0c;只想悄咪咪地执行&#xff0c;那也许下面的文章会…

如何使用pycrypt加密工具测试反病毒产品的检测性能

关于pycrypt pycrypt是一款基于Python 3语言开发的加密工具&#xff0c;广大研究人员可以使用该工具来尝试绕过任意类型的反病毒产品&#xff0c;以检测目标反病毒产品的安全性能。 功能介绍 1、目前已知反病毒产品检测率为0/40&#xff1b; 2、支持绕过任意EDR解决方案&#…

202206青少年软件编程(Python)等级考试试卷(四级)

第 1 题 【单选题】 有如下 Python 程序, 包含 lambda 函数, 运行该程序后, 输出的结果是? ( ) g = lambda x,y:x*yprint(g(2,3))A :2 B :3 C :6 D :8 正确答案:C 试题解析: g = lambda x, y: x*y, lambda 函数返回参数 x 和 y 的积, 因此选 C。 第 2 题 【单选…

深入理解Spring的TransactionSynchronizationManager

在Spring框架中&#xff0c;TransactionSynchronizationManager扮演着事务同步管理的核心角色&#xff0c;它不仅负责跟踪当前活动事务的状态&#xff0c;还提供了在事务生命周期中注册回调方法的能力&#xff0c;使得开发者能够在事务开始、提交、回滚等关键时刻执行自定义逻辑…

中间件-------RabbitMQ

同步和异步 异步调用 MQ MQ优势&#xff1a;①服务解耦 ②异步调用 ③流量削峰 结构 消息模型 RabbitMQ入门案例&#xff0c;实现消息发送和消息接收 生产者&#xff1a; public class PublisherTest {Testpublic void testSendMessage() throws IOException, TimeoutExce…

Java进阶学习笔记21——泛型概念、泛型类、泛型接口

泛型&#xff1a; 定义类、接口、方法的时候&#xff0c;同时声明了一个或者多个类型变量&#xff08;如: <E>&#xff09;,称之为泛型类、泛型接口、泛型方法&#xff0c;我们统称之为泛型。 说明这是一个泛型类。 如果不使用泛型&#xff0c;我们可以往ArrayList中传…

PyQt6--Python桌面开发(34.QStatusBar状态栏控件)

QStatusBar状态栏控件 self.statusBar.showMessage(q.text()菜单选项被点击了,5000)

泛型擦除带来的问题有哪些

泛型擦除&#xff08;Type Erasure&#xff09;在Java中是一个重要的概念&#xff0c;它是Java泛型实现的一部分&#xff0c;用于在编译时检查类型安全&#xff0c;但在运行时取消这些类型信息以保持与旧版本Java的兼容性。然而&#xff0c;泛型擦除也带来了一些问题&#xff0…

Django模型字段

字段选项 null 如果是 True&#xff0c; Django 将在数据库中存储空值为 NULL。默认为 False。 避免在基于字符串的字段上使用 null&#xff0c;如 CharField 和 TextField。如果一个基于字符串的字段有 nullTrue&#xff0c;这意味着它有两种可能的“无数据”值。NULL&…

平安养老险陕西分公司:举办“贺司庆·员工橙心面对面”活动

为践行新价值文化与“三省”推广&#xff0c;平安养老险陕西分公司以集团36周年司庆为契机结合“员工聆听计划”指引要求&#xff0c;举办“贺司庆&#xff0c;员工橙心面对面”活动。 活动邀请西北大学公共管理学院高阳教授为分公司员工带来生动有趣的《压力管理新科学》心理课…

MyBatis-Plus 从入门到精通

MyBatis-Plus 从入门到精通 前言快速入门创建一个SpringBoot项目导入依赖配置数据库创建一个实体类创建一个mapper接口在SpringBoot启动类上配置mapper接口的扫描路径在数据库中创建表编写一个SpringBoot测试类 核心功能注解CRUD接口Mapper CRUD接口Service CRUD 接口条件构造器…

安卓开发--安卓使用Echatrs绘制折线图

安卓开发--安卓使用Echatrs绘制折线图 前期资料安卓使用Echarts绘制折线图1.1 下载 Echarts 安卓资源1.2 新建assets文件1.3 新建布局文件1.4 在布局文件中布局WebView1.5 在活动文件中调用 最终效果 前期资料 Echarts 官网样式预览: https://echarts.apache.org/examples/zh/…