Best practice-ThreadLocal高并发场景的最佳实践

关于ThreadLocal基础信息

引用一段来自ThreadLocal源码中的doc注释来说明其特性:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e. g., a user ID or Transaction ID).

个人理解:该类提供了一个线程级别的变量,不同线程间通过get/set方法可以访问到自己不同的数据副本,ThreadLocal实例通常是类中的私有的静态数据如userId或事务id。

ThreadLocalJava中是一个线程级别的变量,每一个线程都有自己独立的变量,ThreadLocal类型所创建,key是线程信息,value值是数据的副本,其副本值在各个线程间不可见,在并发模式下各个线程会访问到自己对应副本的数据信息。

通过以上特性信息,可以将ThreadLoacl应用在获取信息较为昂贵且上下文中多次使用到的业务场景,用户信息的存储和缓存场景就很适合使用该类。

线程池中的线程重用

前置知识

Spring Boot虽然没有明确配置Tomcat的地方,实则不同Spring Boot版本内置了Tomcat,不同Spring Boot版本与Tomcat版本呈现绑定关系。以下用例为方便复现Spring Boot项目中的线程复用问题,需要手动将Spring Boot的线程池大小设置为1,以保证每次请求都是同一个线程处理请求。Spring Boot 2.1.x版本之后内置Tomcat 9.x,Spring Boot 3.x版本后内置Tomcat 10.x,修properties配置文件为例,修改线程池大小的代码为:

server.tomcat.threads.max=1

yaml配置文件写法:

server:
  tomcat:
    threads:
      max: 1

Spring Boot版本嵌入式Tomcat版本对应关系:

Spring Boot 版本 默认 Tomcat 版本
1.5.x 8.5.x
2.0.x 8.5.x
2.1.x 9.0.x
2.2.x 9.0.x
2.3.x 9.0.x
2.4.x 9.0.x
2.5.x 9.0.x
2.6.x 9.0.x
2.7.x 9.0.x
3.0.x 10.1.x
3.1.x 10.1.x
3.2.x 10.1.x

Spring Boot 2.0.x版本配置:

server.tomcat.max-threads=1

错误实践业务场景

ThreadLocal 在多线程环境下可能导致的线程复用问题,即ThreadLocal没有被清理的情况下,上一个请求的 ThreadLocal 值可能会影响下一个请求

以下代码示例使用ThreadLocal存储用户信息,使用ThreadLocal.withInitial()进行初始化,before表示请求前的值,设置用户信息之前先查询一次ThreadLocal中的用户信息,after表示赋值到ThreadLocal,使用ThreadLocal保存的副本变量。

// String类型表示用户信息
private static final ThreadLocal<String> requestIdThreadLocal = ThreadLocal.w
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值