为了账号安全,请及时绑定邮箱和手机立即绑定

Spring Boot 中的线程本地行为

Spring Boot 中的线程本地行为

萧十郎 2023-07-28 16:43:47
我们知道 Tomcat 有大约 200 个线程,而 Jetty 在各自的线程池中有一些默认计数的线程。因此,如果我们在ThreadLocal每个请求中设置一些内容,它会在线程中终生存在,还是 TomcatThreadLocal在每个请求后清除它。如果我们在过滤器中的 userContext 中设置某些内容,是否需要在每次过滤器退出时清除它?或者如果我们没有线程池配置,Web 服务器是否每次都会创建一个新线程?public static final ThreadLocal<UserContextDto> userContext = new ThreadLocal<>();
查看完整描述

3 回答

?
慕容708150

TA贡献1831条经验 获得超4个赞

是的,你需要清除ThreadLocal。Tomcat 不会清除 ThreadLocals。

不,并不是每次都会创建新线程。池中的线程用于服务请求,并在请求完成后返回池。

这不仅适用于 Tomcat,也适用于 Jetty 和 Undertow。为每个请求创建线程在资源和时间方面都是昂贵的。


查看完整回答
反对 回复 2023-07-28
?
HUX布斯

TA贡献1876条经验 获得超6个赞

不,Tomcat 不会清除您的代码创建的 ThreadLocals,这意味着它们将保留并可能污染后续请求。

因此,每当您创建一个请求时,请确保在同一请求或任何其他请求存在之前将其清除。

还应该注意的是,后续请求 - 即使使用相同的 URL - 也可能在完全不同的线程中执行,因此 ThreadLocal 不是一种在请求之间保存状态的机制。为此,可以使用 SessionBeans 之类的东西。



查看完整回答
反对 回复 2023-07-28
?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

如果您在不是 100% 控制的线程中的 ThreadLocal 中放置了某些内容(即从其他代码调用您的线程,例如 HTTP 请求),则需要在离开代码之前清除您设置的任何内容。

try/finally结构是一个很好的方法。

线程池无法为您做到这一点,因为 Java API 不提供清除线程ThreadLocal变量的方法。(这可以说是Java API的一个缺点)

不这样做会有内存泄漏的风险,尽管它受到线程池大小的限制(如果有的话)。

一旦同一线程再次分配给了解 的代码ThreadLocal,如果您没有删除它,您将看到上一个请求的旧值。依赖于此是不好的。它可能会导致难以追踪的错误、安全漏洞等。


查看完整回答
反对 回复 2023-07-28
  • 3 回答
  • 0 关注
  • 91 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信