您现在的位置是:亿华云 > 应用开发
用ThreadLocal来优化下代码吧
亿华云2025-10-09 01:24:18【应用开发】9人已围观
简介 最近接手了一个老项目,看到一个很有意思的现象。这个项目中大量的方法入参都会带上user信息,比如这样它的意图是希望在方法内使用user的信息,但是如此大范围的传递用户信息,第
最近接手了一个老项目,用T优化看到一个很有意思的下代现象。
这个项目中大量的用T优化方法入参都会带上user信息,比如这样
它的下代意图是希望在方法内使用user的信息,但是用T优化如此大范围的传递用户信息,第一感觉就是下代不优雅。那有什么办法可以优化一下呢?用T优化
我们第一反应是,可以存一个全局变量,下代在初始位置将用户信息存入全局变量,用T优化然后在需要的下代地方去get一下。
那在WEB应用中,用T优化每个请求都是下代一个独立线程,怎么去标记呢?用T优化
可以用线程的id去作为map的key,将该请求的下代用户信息作为map的value。
没错,用T优化Java已经帮我们封装好了这么一个对象,它就是我们今天要说的ThreadLocal。高防服务器
什么是ThreadLocal 如何使用ThreadLocal优化userid层层传递的问题 ThreadLocal原理是啥 ThreadLocal的实战要点1.什么是ThreadLocal先来看下JDK的注释:
简单翻译过来,就是说:
ThreadLocal提供了线程隔离的局部变量,通过get( )和set( )方法操作当前线程对应的变量,而且不会和其他线程冲突,实现了基于线程的数据隔离。2.如何使用ThreadLocal进行优化话不多说,基于我们开头的例子,我迫不及待地用ThreadLocal来优化一下。
2.1 构建基于ThreadLocal的上下文定义一个SessionUser类,存储用户信息,包括用户id、用户名。
然后定义一个基于ThreadLocal的上下文SessionUserContext,代码如下所示。
2.2 信息存入ThreadLocal中在我们的优化案例中,就是存入用户信息。
解析请求中的用户信息有很多方法。云服务器提供商本文以HandlerIntercept为例,说明下MVC中的一种方式。
实现HandlerIntercept接口 重写preHandler方法 解析HttpServletRequest,获取用户信息 用户信息存于SessionUserContext源码如下所示。
2.3 在需要的地方获取信息原本需要传入CurrentUser的参数都可以去掉了。
在需要用户信息的时候,直接从SessionUserContext中获取即可。
哈哈,是不是看起来一下子清爽了很多。
可以在任何地方获取user信息,不再需要层层传递用户信息了。
3.ThreadLocal实现原理上面我们已经知道了怎么通过ThreadLocal进行优化。
下面,我们要 知其然知其所以然,一起看看ThreadLocal实现原理吧。
3.1 set方法Set方法应该是ThreadLocal的核心逻辑了。
主要三步:
获取当前线程
获取ThreadLocalMap对象 如果ThreadLocalMap对象存在,则将当前线程对象作为key,要存储的对象作为value存到map中 如果ThreadLocalMap对象不存在,就调用creatMap( )进行创建3.2 ThreadLocalMap是什么。ThreadLocalMap是一个定义在ThreadLocal类内部的静态类,免费信息发布网里面还定义了一个Entry类作为存储值的地方。
ThreadLocalMap的key是当前ThreadLocal对象,value是我们要存储的值(对象)。
调用creatMap的时候,就是新建一个ThreadLocalMap对象
同时,ThreadLocalMap在Thread类中作为一个属性存在。
每个线程Thread维护了ThreadLocalMap这么一个Map,这个map的key是LocalThread对象本身,value则是要存储的对象
3.3 get方法Get方法就比较简单了,就是从map中取值的过程。
3.4 ThreadLocal小结现在,让我们重新梳理一遍,看看ThreadLocal是如何实现变量的线程隔离的:
每个Thread维护着一个ThreadLocalMap的引用
ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储,key是ThreadLocal对象,值是传递进来的对象
调用ThreadLocal的get()/set()方法时,实际上就是以ThreadLocal对象为key,在ThreadLocalMap中读写value
4.实战要点在一开始的优化设计中,不知道大家有没有注意到对ThreadLocal的remove调用。
这里就需要谈谈ThreadLocal使用时的,两个要点。尤其是在使用线程池的时候使用ThreadLocal。
4.1 避免内存泄露
在ThreadLocalMap介绍的时候,我们可以看到,ThreadLocalMap是Thread的一个属性。因此,ThreadLocalMap和Thread的生命周期是一样的。
如果没有手动删除对应的ThreadLocal的key,那么就会造成内存泄漏无法回收。尤其在线程池环境下,线程会被不断复用。
4.2 线程池避免重复线程变量影响以上文优化案例为例。
在MVC中,每次请求进来会使用线程池复用线程。如果请求带了用户信息,那么就会重置ThreadLocal对应的用户信息,如果请求没有带用户信息,必须手动清除一下当前ThreadLocal对应的变量,否则后面使用过程中可能会造成混乱。
很赞哦!(979)
相关文章
- 4、域名传输时,取决于域名原始用户的邮箱是否有效,以及他是否将密码发送到此邮箱。
- PostgreSQL 开始支持 Zstd
- 去字节面试被面这题能答上来吗?谈谈你对时间轮的理解?
- 你会看 MySQL 的执行计划(EXPLAIN)吗?
- 打开https://www.aizhan.com/输入自己想要查询的域名然后按回车键,如果做过网站都会有数据显示出来
- 为K线序列管理添加变动百分比属性,和一个简单分析
- LeetCode 算法 | 两数之和不简单啊
- 用DataFrame作为容器分析市场行情指标
- 在数以亿计的网站中,我们应该抓住每一个可能带来宣传的机会,域名可以带有企业的名字,一般可以使用汉语拼音或者英语单词或者是相关缩写的形式,只要用户记住了你企业的名字,就能很容易的打出你的网站域名,同样的,记住了网站域名也能很快的记住你公司的名字。
- MySQL常用查询Databases和Tables