一个故事讲明白线程的私家领地:ThreadLocal

详解ThreadLocal和其中的应用场景 好了,本篇ThreadLocal的相关知识就分享到这里了。 阅读详情

张大胖上午遇到了一个棘手的问题,他在一个AccountService中写了一段类似这样的代码:

Context ctx = new Context();
ctx.setTrackerID(.....)

然后这个AccountService 调用了其他Java类,不知道经过了多少层调用以后,最终来到了一个叫做AccountUtil的地方,在这个类中需要使用Context中的trackerID来做点儿事情:

640?wx_fmt=png

很明显,这个AccountUtil没有办法拿到Context对象, 怎么办?

张大胖想到,要不把Context对象一层层地传递下去,这样AccountUtil不就可以得到了吗?

640?wx_fmt=png

可是这么做改动量太大!涉及到的每一层函数调用都得改动,有很多类都不属于自己的小组管理,还得和别人协调。 

更要命的是有些类根本就没有源码,想改都改不了。

这也难不住我,张大胖想:可以把那个set/get TrackerID的方法改成静态(static)的,这样不管跨多少层调用都没有问题!

public class Context{
    public static String getTrackerID(){
        ......
    }
    public static void setTrackerID(String id){
        ......
    }
}

640?wx_fmt=png

这样就不用一层层地传递了,Perfect!

张大胖得意洋洋地把代码提交给Bill做Review。 

Bill看了一眼就指出了致命的问题: 多线程并发的时候出错!

张大胖恨不得找个地缝钻进去:又栽在多线程上面了,这次犯的还是低级错误!

线程1调用了Context.setTrackerID(), 线程2 也调用了Context.setTrackerID(),数据互相覆盖,不出乱子才怪。

张大胖感慨地说:“像我这样中情况,需要在某处设置一个值,然后经过重重方法调用,到了另外一处把这个值取出来,又要线程安全,实在是不好办啊, 对了,我能不能把这个值就放到线程中? 让线程携带着这个值到处跑,这样我无论在任何地方都可以轻松获得了!”

Bill说:“有啊,每个线程都有一个私家领地! 在Thread这个类中有个专门的数据结构,你可以放入你的TrackerID,然后到任何地方都可以把这个TrackerID给取出来。”

“这么好? ” 

张大胖打开JDK中的Thread类,仔细查看,果然在其中有个叫做threadLocals的变量,还是个Map类型 , 但是在Thread类中却没有对这个变量操作的方法。 

看到张大胖的疑惑,Bill说:“也许你注意到了,这个变量不是通过Thread的访问的,对他的访问委托给了ThreadLocal这个类。”

“那我怎么使用它?”

“非常简单, 你可以轻松创建一个ThreadLocal类的实例:

ThreadLocal<String> threadLocalA= new ThreadLocal<String>();

线程1: threadLocalA.set("1234");
线程2: threadLocalA.set("5678");

像‘1234’, ‘5678’这些值都会放到自己所属的线程对象中。”

640?wx_fmt=png

“等你使用的时候,可以这么办:”

线程1: threadLocalA.get()  --> "1234"
线程2: threadLocalA.get() --> "5678"

“明白了,相当于把各自的数据放入到了各自Thread这个对象中去了,每个线程的值自然就区分开了。 可是我不明白的是为什么那个数据结构是个map 呢?”

“你想想,假设你创建了另外一个threadLocalB:”

ThreadLocal<Integer> threadLocalB = new ThreadLocal<Integer>();

线程1: threadLocalB.set(30);
线程2: threadLocalB.set(40);

那线程对象的Map就起到作用了:

640?wx_fmt=png

“明白了,这个私家领地还真是好用,我现在就把我那个Context给改了,让它使用ThreadLocal:”

public class Context {
    private static final ThreadLocal<String> mThreadLocal 
        = new ThreadLocal<String>();

    public static void setTrackerID(String id) {
        mThreadLocal.set(id); 
    }   
    public static String getTrackerID() {
        return mThreadLocal.get();
    }   

}

小结:

ThreadLocal这个名字起得有点让人误解, 很容易让人认为是“本地线程”, 其实是用来维护本线程的变量。 对照着上面的原理讲解,我想大家可以自行去看ThreadLocal的源码,轻松理解。

ThreadLocal 并不仅仅是Java中的概念,其他语言例如Python,C#中也有,作用类似。

ThreadLocal在日常工作中用得不多,但是在框架(如Spring)中是个基础性的技术,在事务管理,AOP等领域都能找到。

(完)

你看到的只是冰山一角, 更多精彩文章,请移步《2016文章精华》或者《2017文章精华》


码农翻身

用故事讲述技术

640

基于知识图谱的旅游推荐系统 这一系统整合了当今先进的数据技术:采集携程等大型平台的景点数据,通过爬虫技术源源不断地获取最新的旅游信息。此外,我们采用Neo4j图数据库来存储和处理这些数据,结合自然语言处理技术,为你提供精准的旅游建议。:通过直观的知识图谱展示,了解各个景点之间微妙的联系,无论是文化背景还是地理方位,你都能从中发现新的旅行灵感。准备毕业设计的同学,关注我们,这是一个集成了多种前沿技术的项目,为你的学术成果锦上添花。:不再浪费时间,系统根据你的偏好和历史评分,利用协同过滤技术推荐适合的旅游目的地。 阅读详情

相关推荐

simulink求解器选择的小tip

给出了simulink选择求解器的一种tip,与积分初值有关。

高能阿博特的博客 2054

多线程中的ThreadLocal

1.ThreadLocal概述 多线程的并发问题主要存在于多个线程对于同一个变量进行修改产生的数据不一致的问题,同一个变量指的值同一个对象的成员变量或者是同一个类的静态变量。之前我们常听过尽量不要使用静态变量,会引起并发问题,那么随着Spring框架的深入人心,单例中的成员变量也出现了多线程并发问题。Struts2接受参数采用成员变量自动封装,为此在Spring的配置采用多例模式,而Spring...

梁海江的博客 1092

永磁同步电机控制笔记:foc控制原理通俗讲义

引言 到此为止,永磁同步电机控制相关文章已经写了7篇,其中simulink仿真系列文章5篇,控制笔记系列文章2篇,恍惚间感觉少了一篇概论,在此插入一篇,也算是对入坑电机控制一年半来的知识梳理。 文章目录引言一、同步电机是怎么转起来的二、什么样的旋转磁场效率最高三、怎么精准控制旋转磁场的方向四、怎样调节dq轴电流 一、同步电机是怎么转起来的 永磁同步电机结构如下: 外围是定子绕组,中间为永磁体,设...

搞电机的博客 2万+

ThreadLocal类的使用

线程中变量值的共享可以使用public static变量的形式,所有的线程都使用同一个public static变量。那么如果想实现每一个线程都有自己的私有共享变量该怎么实现?可以使用Java的JDK中提供的ThreadLocal类实现这样的功能。 ThreadLocal类主要解决的就是每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存储每个线程的私有数据...

forever-and-ever的博客 365

【YOLOv8实战】从零构建番茄成熟度智能检测GUI系统【附完整工程】

本文详细介绍了从零构建基于YOLOv8的番茄成熟度智能检测GUI系统的完整实战流程。内容涵盖环境搭建、数据集准备、模型训练调优,并重点讲解如何使用PyQt5开发图形界面,最终将项目打包为可执行文件,实现AI模型从训练到桌面应用落地的完整工程闭环。

xxx12的博客 821

uniapp运行钉钉小程序

因项目原因,公司需要在钉钉里面开发小程序。之前用uniapp开发过app,H5,小程序。还真没尝试过钉钉小程序,今天就简单的记录下uniapp运行钉钉小程序中的过程。

YL 2919

ThreadLocal用法

使用场景1 每个线程需要一个独享对象(通常是工具类,典型需要使用的类有SimpleDateFormat和Random) 每个Thread内有自己的实例副本,不共享 比喻:教材只有一本,一起做笔记有线程安全问题。复印后没有问题,使用ThradLocal相当于复印了教材。 将可能会发生线程冲突的类作为ThreadLocal的泛型: //内部类,下面可以直接使用 class ThreadSafeForm...

ZHUSHANGLIN的博客 326

【GlobalMapper精品教程】027:路径剖面和和视线工具的使用

路径剖面视线工具允许您使用加载的高程数据集沿用户指定的路径获取垂直剖面。要定义生成3D路径剖面所遵循的路径,只需单击鼠标左键选择路径的点,然后石键单击以结束路径。出现一个带有剖面的对话框,允许您设置视线分析或优化端点。

智慧空间实验室 2048

一个故事讲明白 ThreadLocal

点击上方“程序员小灰”,选择“置顶公众号”有趣有内涵的文章第一时间送达!本文转载自公众号  码农翻身张大胖上午遇到了一个棘手的问题,他在一个AccountService中写了一段类似这样的代码:Context ctx = new Context();ctx.setTrackerID(.....)然后这个AccountService 调用了其他Java类,不知道经过了多少层调用以后,最终来到了一个叫

程序员小灰的博客 1394

静态时序分析(STA)基本概念

静态时序分析中常见概念(fasle Path,multicycle path等)

m0_61544122的博客 2255

FAST-LIO论文公式解析

FAST-LIO论文公式解析

努力努力努力 670

一个故事讲明白 ThreadLocal,是真的一看就懂!!!

张大胖上午遇到了一个棘手的问题,他在一个AccountService中写了一段类似这样的代码: Context ctx = new Context();ctx.setTrackerID(.....)然后这个AccountService 调用了其他Java类,不知道经过了多少层调用以后,最终来到了一个叫做AccountUtil的地方,在这个类中需要使用Context中的trackerID来做点儿事情...

哆啦A梦丶幻想的博客 575

【智能车Code review】——拐点的寻找

CROSSROAD:十字拐点 ROUNDISLAND:环岛拐点 rightfindflag[i]:表示第i行的右线是否被找到,1为找到,0为没有找到 flag_find_huan_rightdown_point :找到环岛右下拐点标志 flag_find_huan_rightmiddle_point:找到环岛右中拐点标志 找拐点的思路:观察一段数据中数据点的走向趋势,并且保证这段数据是准确的。在摄像头畸变比较严重的情况下这种方法不再适用 关于函数的调用请见:https://blog.youkuaiyun.com/qq.

hanhan的博客 1万+

threadlocal使用_使用 ThreadLocal 一次解决老大难问题

点击上方 "程序员小乐"关注, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 Sometimes,you are not happy if you see through everything.It's better to be naive and inattentive. 很多时候,看的太透反而不快乐,倒不如幼稚的没心没肺。 每日掏心话 人生,何必扭扭捏捏。生活,何苦畏...

weixin_39980347的博客 170

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

使用 ThreadLocal 一次解决老大难问题

点击上方 "程序员小乐"关注,星标或置顶一起成长 每天凌晨00点00分,第一时间与你相约 每日英文 Sometimes,you are not happy if you see through everything.It's better to be naive and inattentive. 很多时候,看的太透反而不快乐,倒不如幼稚的没心没肺。 每日掏心话 人生,何必扭扭...

吧主 340

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

从源码看ThreadLocal的底层结构

引言 set() get() 总结

binaryshao 1473

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

码农翻身公众号文章阅读--笔记整理

码农翻身公众号的文章阅读笔记记录, 这个公众号以通俗易懂的语言和幽默的漫画来表达计算机技术,能够让人有代入感,且能够愉快的学习,非常值得大家去阅读学习。现将自己之前的笔记整理,算是温故而知新。

wangchaodee的博客 548

小白科普:“无状态”那点事儿

前言: 周一推送的干货文章有点难了,今天来个轻松一点儿的!软件大师正在闭目修炼, 最小的一名弟子慢慢走了进来。大师,弟子有一事不明,甚是烦恼。说来听听,让为师给你排解一下...

码农翻身 451

java中ThreadLocal类的使用

ThreadLocal是解决线程安全问题一个很好的思路,ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本,由于Key值不可重复,每一个“线程对象”对应线程的“变量副本”,而到达了线程安全。 我们知道Spring通过各种DAO模板类降低了开发者使用各种数据持久技术的难度。这些...

不积跬步 无以至千里 不积小流 无以成江海 633

如何正确使用 ThreadLocal,你真的用对了吗?

前言当多线程访问共享且可变的数据时,涉及到线程间同步的问题,并不是所有时候,都要用到共享数据,所以就需要ThreadLocal出场了。ThreadLocal又称线程本地变量,使用其能够将数据封闭在各自的线程中,每一个ThreadLocal能够存放一个线程级别的变量且它本身能够被多个线程共享使用,并且又能达到线程安全的目的,且绝对线程安全,其用法如下所示:public...

weixin_45737309的博客 644

ThreadLocal源码分析---相同线程数据共享,不同线程数据隔离

本来是想说下java中的Thread的,毕竟之前就写了join和Thread的状态,本来想把下面的也说了,不过碰到了一只拦路虎ThreadLocal,两者有许多关联,为了彻底搞清楚Thread,还是要先说一说ThreadLocal,所以又回到了这里。 ThreadLocal 大家应该都有些熟悉,刚刚开始熟悉java的时候,大伙往数据库里面写数据,需要创建数据库连接,不知道大家当时有没有遇到过连接被占用的问题,\(^o^)/~,查资料之后才知道要使用ThreadLocal,当然,现在...

zsah2011的博客 978

如何正确使用 ThreadLocal

如何正确使用 ThreadLocal

吴名氏的博客 9万+
上一篇: 一个项目做完以后,不能就让它这么“完”了
下一篇: 2018,开通一个交流新渠道!
码农翻身
码农翻身 《码农翻身》作者 《码农翻身》作者
博客等级 码龄8年 3万+粉丝 1084原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值