ThreadLocal,一个Java人面试绕不开的话题,我也很奇怪为什么那些面试官很喜欢问这个,也不知道他们自己有没有搞清楚。

接下来,我想先说说ThreadLocal的用法和使用场景,然后反问面试官3个关于ThreadLocal的话题

使用方法和场景

一句话总结:ThreadLocal是给每个线程准备一份“独立的小空间”,它让每个线程都拥有自己独立的变量副本。在多个线程并发访问时,不用担心变量之间的冲突问题,避免了多线程之间的数据共享风险。

使用场景

ThreadLocal的使用场景主要在多线程环境中,能够为每个线程提供独立的变量副本。比如:

  • 用户上下文信息:比如,在Web应用中,每个请求可能由不同的线程处理,在处理用户请求时为每个线程维护独立的用户信息。
  • 数据库连接管理:比如,在多线程环境下,每个线程需要有自己独立的数据库连接。
  • 事务管理:比如,在处理事务时,每个线程可能需要有自己的事务上下文,确保线程安全的事务操作。
  • 数据传递:比如,同一个线程,在不同的方法之间传递数据,但又不想使用方法参数去传递,就可以使用ThreadLocal。像我们常用的日志跟踪场景,跟踪的ID会存在ThreadLocal中贯穿整个链条。

总之有2个场景:

  1. 在多线程场景下,每个线程需要独立管理变量的场景。
  2. 某个线程想在整条链路上共享独立变量的场景。

使用方法

使用时,记住3条核心原则:

  • 每个线程都有一份独立的数据。
  • 线程内部使用的是ThreadLocalMap来保存数据,Key就是ThreadLocal对象。
  • 使用完毕后,记得调用remove方法,防止内存溢出。

代码示例

独立保存变量的示例:

public class ThreadLocal4Independent {

    private static ThreadLocal<Integer> threadLocalVar = new ThreadLocal<>();

    public static void main(String[] args) {
Runnable task = () -> {
int num = (int) (Math.random() * 100);
threadLocalVar.set(num);
System.out.println("线程:" + Thread.currentThread().getName() + "的值:" + threadLocalVar.get());
threadLocalVar.remove();
}; new Thread(task, "1").start();
new Thread(task, "2").start();
} }

传递参数的示例:

public class ThreadLocal4DataPass {
// 使用ThreadLocal来存储需要在多个方法间传递的数据
private static final ThreadLocal<String> threadLocalData = new ThreadLocal<>(); public static void main(String[] args) {
// 在主线程中设置数据
threadLocalData.set("ThreadLocal"); // 在主线程中调用不同的方法
method1();
method2(); // 清除ThreadLocal变量,防止内存泄露
threadLocalData.remove();
} private static void method1() {
// 在method1中获取数据并打印
String data = threadLocalData.get();
System.out.println("方法1拿到的数据是:" + data);
} private static void method2() {
// 在method2中获取数据并打印
String data = threadLocalData.get();
System.out.println("方法2拿到的数据是:" + data);
}
}

聊完使用场景和方法,接下来问面试官几个问题。

问题1:请画出ThreadLocal和Thread的关系图

ThreadLocal和Thread的关系图如下。

这里要牢记3点

  1. 数据实际上是存在ThreadLocalMap中的,ThreadLocalMap归Thread所持有。见源代码。

  2. ThreadLocalMap内部使用的是K-V结构,Key是我们定义的ThreadLocal对象。见源代码。

  3. ThreadLocalMap对ThreadLocal是弱引用关系。见源代码。

问题2:为什么ThreadLocalMap里的Key是弱引用

那为什么ThreadLocalMap里的Key是使用ThreadLocal呢?为什么又是弱引用呢?

这就不得不说JDK的设计者的思想非常精妙了,有3点妙处:

  1. 一个线程要是存了多种数据,总得有个规则去找他们,那就根据定义的ThreadLocal对象去找吧。
  2. 对于开发者来说,他只需要使用ThreadLocal去保存数据即可,无需关系底层结构。也就是说对外暴露简单的使用方式即可,对于不需要调用方知道的细节全部隐藏。
  3. 一般情况下Thread的生命周期会很长,比如Web容器启动后,就会启动大量的线程丢到线程池中复用。所以ThreadLocalMap的生命周期也会很长。但是,ThreadLocal对象存在的周期不一定长,如果,ThreadLocalMap的Key对ThreadLocal是强引用的话,那么ThreadLocal对象就会一直存在于内存中得不到释放,最终会导致内存溢出,所以采用了弱引用。

问题3:为什么ThreadLocal使用不当会造成内存溢出

从上图的关系图可以看出,Value的生命周期是跟着Thread的生命周期来的,如果一直不处理的话,也会出现内存溢出的情况。

为了避免内存溢出的情况,我们在使用完ThreadLocal后,要即使调用remove方法,以便JVM回收Value。

总结

ThreadLocal 是并发编程中的强大工具,能够为每个线程提供独立的变量副本,避免线程安全问题。并且这个ThreadLocal存入的值能够贯穿整个流程。使用时要注意上文的几点,防止造成内存溢出。

本篇完结!欢迎 关注、加V(yclxiao)交流、全网可搜(程序员半支烟)

原文链接:https://mp.weixin.qq.com/s/Z3x_tw1jks_KYE0ljETp0Q

反问面试官3个ThreadLocal的问题的更多相关文章

  1. 面试官:知道ThreadLocal嘛?谈谈你对它的理解?(基于jdk1.8)

    https://zhuanlan.zhihu.com/p/99150038   ​ 西北工业大学 计算机技术硕士在读 在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的 ...

  2. 面经手册 · 第12篇《面试官,ThreadLocal 你要这么问,我就挂了!》

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 说到底,你真的会造火箭吗? 常说面试造火箭,入职拧螺丝.但你真的有造火箭的本事吗,大 ...

  3. 走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串

    原文:走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串 对大量数据进行查询时,可以应用到索引技术.索引是一种特殊类型的数据库对象,它保存着数据表中一列或者多列的排序结果,有 ...

  4. 大厂面试官:Java工程师的“十项全能”

    想要成为合格的Java程序员或工程师到底需要具备哪些专业技能,在面试之前到底需要准备哪些东西呢?面试时面试官想了解你的什么专业技能,以下都是一个合格Java软件工程师所要具备的. 一.专业技能 熟练的 ...

  5. 阿里面试官用HashMap把我问倒了

    本人是一名大三学生,最近在找暑期实习,其中也面试过两次阿里,一次菜鸟网络部门.一次网商银行部门,当然我都失败了,同时也让我印象很深刻,因此记录了其中一些面试心得,我觉得这个问题很值得分享,因此分享给大 ...

  6. 面试官:小伙子,听说你看过ThreadLocal源码?(万字图文深度解析ThreadLocal)

    前言 Ym8V9H.png (高清无损原图.pdf关注公众号后回复 ThreadLocal 获取,文末有公众号链接) 前几天写了一篇AQS相关的文章:我画了35张图就是为了让你深入 AQS,反响不错, ...

  7. 硬核剖析ThreadLocal源码,面试官看了直呼内行

    工作面试中经常遇到ThreadLocal,但是很多同学并不了解ThreadLocal实现原理,到底为什么会发生内存泄漏也是一知半解?今天一灯带你深入剖析ThreadLocal源码,总结ThreadLo ...

  8. Java面试必问,ThreadLocal终极篇

    转载自掘金占小狼博客. 前言 在面试环节中,考察"ThreadLocal"也是面试官的家常便饭,所以对它理解透彻,是非常有必要的. 有些面试官会开门见山的提问: “知道Thread ...

  9. 引用面试官文章 :如何准备Java初级和高级的技术面试

    本人最近几年一直在做java后端方面的技术面试官,而在最近两周,又密集了面试了一些java初级和高级开发的候选人,在面试过程中,我自认为比较慎重,遇到问题回答不好的候选人,我总会再三从不同方面提问,只 ...

  10. 一线大厂面试官最喜欢问的15道Java多线程面试题

    前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得更多职位,那么你应该准备很多关于多线程的问题. 他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者 ...

随机推荐

  1. odoo 开发入门教程系列-基本视图

    在上一章中已经看到,odoo能够为给定模型生成默认视图.实际上,默认视图对于业务应用程序来说是不可接受的.相反,我们至少应该以逻辑的方式组织各个字段. 视图是在带有操作和菜单的XML文件中定义的.它们 ...

  2. 使用 Doxygen 来生成 Box2d 的 API 文档

    对于 Doxygen 以前只听别人说过,而现在使用它也是一个偶然,缘分吧.前两天看 box2d 的官方 sdk 中,发现他有用户手册却没有说明,只是留下了一个 Doxygen 的文件.事情告一段落,然 ...

  3. Spring Boot快速入门(二)搭建javaWeb项目

    1.配置pom.xml 教程一创建的项目为maven项目,所以搭建一个Spring Boot的Web项目,先导入一下jar包:即在pom.xml以下依赖: 1 <dependencies> ...

  4. 浅谈 I/O 与 I/O 多路复用

    1.基础知识 网络编程里常听到阻塞IO.非阻塞IO.同步IO.异步IO等概念,总听别人聊不如自己下来钻研一下.不过,搞清楚这些概念之前,还得先回顾一些基础的概念. 下面说的都是Linux环境下,跟Wi ...

  5. app专项测试:app弱网测试(网络测试流程)

    app专项测试:app弱网测试(网络测试流程) 一.网络测试的一般流程 step1:首先要考虑网络正常的情况 ① 各个模块的功能正常可用 ② 页面元素/数据显示正常 step2:其次要考虑无网络的情况 ...

  6. 【NodeJS】操作MySQL

    1.在连接的数据库中准备测试操作的表: CREATE TABLE `user` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', `name` ...

  7. 【RabbitMQ】07 SpringBoot整合RabbitMQ

    生产者和消费者的依赖基本一致: 注意工程名称不是一样的 <?xml version="1.0" encoding="UTF-8"?> <pro ...

  8. 【转载】 Docker-关于docker cpu的限制后,实际效果的研究

    原文地址: https://zhuanlan.zhihu.com/p/46275332 ================================================== 思考:我们 ...

  9. 国产CPU(兆芯 kx-6640) 播放1080p视频效果

    前一阵买了一个国产CPU的主机(国产CPU,国产操作系统UOS--零刻LZX迷你主机 , 显卡驱动安装以及屏幕配置),cpu是兆芯  kx-6640,用来播放1080p的视频虽然不是那么丝滑的流畅,但 ...

  10. NVIDIA显卡cuda的多进程服务——MPS(Multi-Process Service)

    相关内容: tensorflow1.x--如何在C++多线程中调用同一个session会话 tensorflow1.x--如何在python多线程中调用同一个session会话 参考: https:/ ...