简体   繁体   English

Spring Boot中的线程本地行为

[英]Thread local behaviour in spring boot

As we know Tomcat has approx 200 threads and Jetty has some default count threads in their respective thread pools. 众所周知,Tomcat大约有200个线程,而Jetty在它们各自的线程池中都有一些默认计数线程。 So if we set something in a ThreadLocal per request, will it be there in the thread for life time or will Tomcat clear the ThreadLocal after each request. 因此,如果我们为每个请求在ThreadLocal设置某些内容,它将在线程中存在一生,还是在每次请求后Tomcat清除ThreadLocal

If we set something in userContext in a filter do we need to clear it every time the filter exits? 如果我们在过滤器的userContext中设置某些内容,是否需要在每次过滤器退出时将其清除?

Or will the web server create a new thread every time, if we don't have a thread pool configuration? 还是如果我们没有线程池配置,Web服务器是否每次都会创建一个新线程?

public static final ThreadLocal<UserContextDto> userContext = new ThreadLocal<>();

No, Tomcat will not clear ThreadLocals that your code creates, which means they will remain and could pollute subsequent requests. 不会,Tomcat不会清除您的代码创建的ThreadLocals,这意味着它们将保留并可能污染后续请求。

So whenever you create one, make sure you clear it out before that same request or whatever exits. 因此,无论何时创建一个,请确保在同一请求或其他退出之前将其清除。

It should also be noted that subsequent requests - even using the identical URL - could well be executed in a totally different thread, so ThreadLocals are not a mechanism for saving state between requests. 还应注意,后续请求(即使使用相同的URL)也可以在完全不同的线程中执行,因此ThreadLocals不是一种用于在请求之间保存状态的机制。 For this, something like SessionBeans could be used. 为此,可以使用像SessionBeans这样的东西。

If you put something in a ThreadLocal in a Thread that is not 100% under your control (ie one in which you are invoked from other code, like for a HTTP request), you need to clear whatever you set before you leave your code. 如果您将某个内容放到了不是100%处于您控制之下的Thread的ThreadLocal中(即从其他代码中调用您的内容,例如HTTP请求),则需要在离开代码之前清除所有设置。

A try / finally structure is a good way to do that. try / finally结构是实现此目的的好方法。

A threadpool can't do it for you, because the Java API does not provide a way to clear a thread's ThreadLocal variables. 线程池无法为您完成此操作,因为Java API没有提供清除线程的ThreadLocal变量的方法。 (Which is arguably a shortcoming in the Java API) (可以说这是Java API的缺点)

Not doing so risks a memory leak, although it's bounded by the size of the thread pool if you have one. 如果不这样做,则存在内存泄漏的风险,尽管如果存在线程泄漏,则受线程池的大小限制。

Once the same thread gets assigned again to the code that knows about the ThreadLocal , you'll see the old value from the previous request if you didn't remove it. 一旦将相同的线程再次分配给了解ThreadLocal的代码,如果不删除它,您将看到上一个请求中的旧值。 It's not good to depend on that. 依靠它是不好的。 It could lead to hard to trace bugs, security holes, etc. 它可能导致难以跟踪的错误,安全漏洞等。

Yes, you need to clear ThreadLocal. 是的,您需要清除ThreadLocal。 Tomcat won't clear ThreadLocals. Tomcat不会清除ThreadLocals。

No, new thread is not created every time. 不,不是每次都创建新线程。 A thread from the pool is used to serve a request, and returned back to pool once request is complete. 来自池的线程用于处理请求,并在请求完成后返回到池。

This not only applies to Tomcat, it applies to Jetty and Undertow as well. 这不仅适用于Tomcat,还适用于Jetty和Undertow。 Thread creation for every request is expensive in terms of both resources and time. 就资源和时间而言,为每个请求创建线程都是昂贵的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM