ThreadLocal的几个误区和使用

最近由于需要用到ThreadLocal,在网上搜索了一些相关资料,发现对ThreadLocal经常会有下面几种误解

一、ThreadLocal是java线程的一个实现
ThreadLocal的确是和java线程有关,不过它并不是java线程的一个实现,它只是用来维护本地变量。针对每个线程,提供自己的变量版本,主要是为了避免线程冲突,每个线程维护自己的版本。彼此独立,修改不会影响到对方。

二、ThreadLocal是相对于每个session的

ThreadLocal顾名思义,是针对线程。在java web编程上,每个用户从开始到会话结束,都有自己的一个session标识。但是ThreadLocal并不是在会话层上。其实,Threadlocal是独立于用户session的。它是一种服务器端行为,当服务器每生成一个新的线程时,就会维护自己的ThreadLocal。对于这个误解,个人认为应该是开发人员在本地基于一些应用服务器测试的结果。众所周知,一般的应用服务器都会维护一套线程池,也就是说,对于每次访问,并不一定就新生成一个线程。而是自己有一个线程缓存池。对于访问,先从缓存池里面找到已有的线程,如果已经用光,才去新生成新的线程。所以,由于开发人员自己在测试时,一般只有他自己在测,这样服务器的负担很小,这样导致每次访问可能是共用同样一个线程,导致会有这样的误解:每个session有一个ThreadLocal

三、ThreadLocal是相对于每个线程的,用户每次访问会有新的ThreadLocal

理论上来说,ThreadLocal是的确是相对于每个线程,每个线程会有自己的ThreadLocal。但是上面已经讲到,一般的应用服务器都会维护一套线程池。因此,不同用户访问,可能会接受到同样的线程。因此,在做基于TheadLocal时,需要谨慎,避免出现ThreadLocal变量的缓存,导致其他线程访问到本线程变量

四、对每个用户访问,ThreadLocal可以多用
可以说,ThreadLocal是一把双刃剑,用得来的话可以起到非常好的效果。但是,ThreadLocal如果用得不好,就会跟全局变量一样。代码不能重用,不能独立测试。因为,一些本来可以重用的类,现在依赖于ThreadLocal变量。如果在其他没有ThreadLocal场合,这些类就变得不可用了。个人觉得ThreadLocal用得很好的几个应用场合,值得参考

1、存放当前session用户:quake want的jert

2、存放一些context变量,比如webwork的ActionContext

3、存放session,比如Spring hibernate orm的session
### Java `ThreadLocal` 工作原理 `ThreadLocal` 是一种特殊的变量容器,允许每个线程拥有该变量的一个独立副本。这意味着同线程之间无法相互干扰彼此持有的 `ThreadLocal` 变量实例[^1]。 具体来说,在 JVM 中每一个线程都维护着一个名为 `ThreadLocalMap` 的哈希表结构来保存这些特定于当前线程的数据项。每当调用 `set()` 方法向某个 `ThreadLocal` 对象赋值时,实际上是在对应的线程内部创建了一个键值对记录;当通过 `get()` 获取值的时候,则是从这个映射关系里查找并返回相应的对象引用[^2]。 对于继承自父级线程属性的情况(即 `InheritableThreadLocal`),JVM 还会复制一份来自父进程的相关配置给新启动的孩子们使用[^3]。 ```java public class ThreadLocalExample { private static final ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0); public void increment() { Integer value = threadLocalValue.get(); threadLocalValue.set(value + 1); } public int getValue() { return threadLocalValue.get(); } } ``` 这段代码展示了如何定义一个初始值为零 (`withInitial`) 的整数类型的 `ThreadLocal` 实例,并实现了两个方法用于操作其上的数值——增加计数器(`increment`) 读取当前值(`getValue`)。 ### 应用场景 #### 数据库连接池管理 在一个典型的Web应用服务器环境中,多个请求可能并发执行数据库查询任务。为了提高性能资源利用率,通常采用连接池技术预先分配一定数量的数据库链接供后续重用。此时就可以利用 `ThreadLocal` 来确保每次HTTP请求处理过程中所使用的都是同一个持久化的Session对象,从而简化事务管理错误恢复逻辑[^4]。 #### 用户上下文传递 假设存在一个多租户SaaS平台架构下的微服务组件通信链路,其中涉及到跨层传播认证信息的需求。借助 `ThreadLocal` ,可以在进入业务流程之初就将登录用户的唯一标识符存入内存空间内,之后无论经过多少次函数调用跳转都会丢失这条重要线索,直到整个交易结束为止自动清除掉临时缓存的内容。 #### 并发计算中的状态保持 考虑这样一个例子:有一个复杂的算法需要分成若干个小部分由同的工作单元协同完成。如果希望各个子任务能够共享某些中间结果而必担心同步竞争条件带来的麻烦的话,那么完全可以把它们封装成静态字段形式并通过 `ThreadLocal` 方式来进行分发控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值