【面试题2020-03-31】说说你对ThreadLocal的理解

思路:

  0.ThreadLocal是什么?有什么用?

  1.ThreadLocal用在什么地方?

  2.ThreadLocal的一些细节

  3.ThreadLocal的最佳实践

一.ThreadLocal用在什么地方?

  讨论ThreadLocal用在什么地方前,我们先明确下,如果仅仅就一个线程,那么都不用谈ThreadLocal的,ThreadLocal是用在多线程的场景的!!!

  ThreadLocal归纳下来就2类用途:

    1.保存线程上下文信息,在任意需要的地方可以获取!!!

    2.线程安全的,避免某些情况需要考虑线程安全必须同步带来的性能损失!!!

  

  保存线程上下文信息,在任意需要的地方可以获取!!!

  由于ThreadLocal的特性,同一线程在某地方进行设置,在随后的任意地方都可以获取到。从而可以用来保存线程上下文信息。

常用的比如每个请求怎么把一串后续关联起来,就可以用ThreadLocal进行set,在后续的任意需要记录日志的方法里面进行get获取到请求id,从而把整个请求串起来。

还有比如Spring的事务管理,用ThreadLocal存储Connection,从而各个DAO可以获取同一Connection,可以进行事务回滚,提交等操作。

  线程安全的,避免某些情况需要考虑线程安全必须同步带来的性能损失!!!

  ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。但是ThreadLocal也有局限性,我们来看看阿里规范:

  每个线程往ThreadLocal中读写数据是线程隔离,互相之间不会影响的,所以ThreadLocal无法解决共享对象的更新问题!

二.ThreadLocal的一些细节

Thread、ThreadLocalMap、ThreadLocal总览图:

  Thread类有属性变量threadLocals (类型是ThreadLocal.ThreadLocalMap),也就是说每个线程有一个自己的ThreadLocalMap ,所以每个线程往这个ThreadLocal中读写隔离的,并且是互相不会影响的。

  一个ThreadLocal只能存储一个Object对象,如果需要存储多个Object对象那么就需要多个ThreadLocal!!!

看到上面的几个图,大概思路应该都清晰了,我们Entry的key指向ThreadLocal用虚线表示弱引用 ,下面我们来看看ThreadLocalMap:

java对象的引用包括 :强引用,软引用,弱引用,虚引用 。因为这里涉及到弱引用,简单说明下:弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,该对象仅仅被弱引用关联,那么就会被回收。

当仅仅只有ThreadLocalMap中的Entry的key指向ThreadLocal的时候,ThreadLocal会进行回收的!!!

ThreadLocal被垃圾回收后,在ThreadLocalMap里对应的Entry的键值会变成null,但是Entry是强引用,那么Entry里面存储的Object,并没有办法进行回收,所以ThreadLocalMap 做了一些额外的回收工作。

三.ThreadLocal的最佳实践

由于线程的生命周期很长,如果我们往ThreadLocal里面set了很大很大的Object对象,虽然set、get等等方法在特定的条件会调用进行额外的清理,但是ThreadLocal被垃圾回收后,在ThreadLocalMap里对应的Entry的键值会变成null,但是后续在也没有操作set、get等方法了。

所以最佳实践,应该在我们不使用的时候,主动调用remove方法进行清理。

这里把ThreadLocal定义为static还有一个好处就是,由于ThreadLocal有强引用在,那么在ThreadLocalMap里对应的Entry的键会永远存在,那么执行remove的时候就可以正确进行定位到并且删除!!!

最佳实践做法应该为:

抽象为:

try {    // 其它业务逻辑} finally {    threadLocal对象.remove();}

如果面试的时候,可以把上面的内容都可以讲到,个人觉得就非常好了,回答的就挺完美了。但是如果你可以进行下面的回答,那么就更完美了。

对于ThreadLocal,我在看Netty源码的时候,还了解过FastThreadLocal,xxxxx一些列内容,那就是一个升级了。

原文地址:https://www.cnblogs.com/july-sunny/p/12602383.html

时间: 2024-08-25 17:59:46

【面试题2020-03-31】说说你对ThreadLocal的理解的相关文章

FFmpeg static build - MinGW32-GCC-5.3.0_x86-x64_D_Drive_for_FFmpeg_static_2016.03.31

算是最终版本,暂不更新 下载地址 MinGW32-GCC-5.3.0_x86-x64_D_Drive_for_FFmpeg_static_2016.03.31.7z 下载地址 ffmpeg-20160331-snapshot-bin.7z autoopts.pc AutoOpts 33.2.8 caca++.pc caca++ 0.99.beta18 caca.pc caca 0.99.beta18 celt.pc celt 0.11.3 dcadec.pc dcadec 0.2.0 fdk-a

18.03.31 顺时针旋转90°24位真彩色bmp图片

1 #include <iostream> 2 #include <fstream> 3 #include <fstream> 4 #include <Windows.h> 5 6 using namespace std; 7 8 int main(int argc,char*argv[]) 9 { 10 tagBITMAPFILEHEADER a;//头信息块 11 tagBITMAPINFOHEADER b;//描述块 12 ifstream fin(a

【程序员面试金典】面试题 01.03. URL化

题目 URL化.编写一种方法,将字符串中的空格全部替换为%20.假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的"真实"长度.(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作.) 示例1: 输入:"Mr John Smith ", 13 输出:"Mr%20John%20Smith" 示例2: 输入:" ", 5 输出:"%20%20%20%20%20" 提示: 字符串长度在[0,

2020/03/05 生成模型&amp;生成学习(Generative Learning)的流程

在之前的学习2020/01/02 深度学习数学基础学习--朴素贝叶斯中,大概的了解了生成学习的原理,但是对算法实现的 完整流程 不够清晰,所以今天想通过对生成学习回顾,明确一下生成学习的流程框架. 学习资料:斯坦福CS229-note2-Generative Learning algorithms的1.2节 必要的概念 类别先验概率: \(P(c)\) 类条件概率: \(P(\vec x | c)\) ,其中\(\vec x=(x_{1},x_{2},...,x_{m}); m为属性\),\(\

2017/03/31学习笔记

双向链表 单向链表的节点都只有一个指向下一个节点的指针单向链表的数据元素无法直接访问其前驱元素逆序访问单向链表中的元素时极其耗时的操作双向链表在单向链表的基础上增加了指向前驱的指针功能上双向链表可以完全取代单向链表的使用 栈是一种特殊的线性表 栈仅能在线性表的一端进行操作栈顶:允许操作的一端栈底:不允许操作的一端首先它是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系.只不过它是一种特殊的线性表.定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底.他的特殊之处就在于

&ldquo;耐撕&rdquo;团队 2016.03.31 站立会议

1. 时间: 19:30--19:50  共计20分钟. 2. 成员: Z 郑蕊 * 组长 (博客:http://www.cnblogs.com/zhengrui0452/), P 濮成林(博客:http://www.cnblogs.com/charliePU/), Q 齐嘉亮(博客:http://www.cnblogs.com/dendroaspis-polylepis/), L  刘伟硕(博客:http://www.cnblogs.com/WeSure6/) 注:Z因个人原因,未能参加本次会

Cheatsheet: 2017 03.01 ~ 03.31

Web New Year, New Blog Day 10 - Using JetBrains Rider with a .NET Core Console Application JavaScript Interview Day # 1: How to create a Class Using React, Redux and Webpack with Dotnet Core to build a modern web frontend Learn Redis the hard way (in

Cheatsheet: 2016 03.01 ~ 03.31

JAVA Quick Java 8 or Java 7 Dev Environments With Docker Printing arrays by hacking the JVM Mobile How to Create a News Reader With React Native: Web Page Component Managing Mobile Performance Optimization Android From Scratch: Building Your First An

【Linux下安装使用virtualenv与virtualenvwrapper】 -- 2019-08-08 18:03:31

原文: http://106.13.73.98/__/95/ virtualenv virtualenv是一个可以帮助我们管理不同Python环境的绝好工具. virtualenv是一个可以在系统中建立多个不同且相互不干扰的虚拟环境. 下面的步骤将创建两个独立的虚拟环境,并分别安装运行django1.11.11.djagno2.0. # 我们先升级pip pip3.6 install --upgrade pip # 指定清华源下载virtualenv pip3.6 install -i http

2020.1.31字符串_查找方法

indexOf(): [格式]字符串.indexof(字串,开始查找的位置):     返回值:第一次出现的位置,否则返回-1 1 var str="abcabcabc"; 2 3 alert(str.indexOf("abc")); 4 //0 5 alert(str.indexOf("abcd")); 6 //-1 7 alert(str.indexOf("abc",1)); 8 //3 lastindexOf(): 与i