在Java中,当修改ThreadLocal对象时,更改会在下一个请求中保留吗?
在典型的 Web 应用程序中,当请求传入时,过滤器会在 http 会话中查找 Context 对象。如果不存在,它会创建 Context 对象并将其存储在 http 会话中。另外,这个Context对象也存储在ThreadLocal对象中。沿路径向下的 Servlet 从 ThreadLocal 检索此 Context 对象并修改它。当返回响应时,过滤器现在将 ThreadLocal 中的 Context 对象清空。那么当用户发出另一个请求时,他能看到修改后的 Context 对象吗?
谢谢 四方
In a typical web application, when a request comes in, a filter looks for a Context object in http session. If one doesn't exist, it creates the Context object and stores it in http session. Additionally, this Context object is also stored in the ThreadLocal object. A Servlet down the path retrieves this Context object from ThreadLocal and modifies it. When the response is returned, the filter now nulls the Context object in ThreadLocal. So when the user makes another request, will he able to see the modified Context object?
Thanks
Quadir
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
是的,用户将看到 Context 对象,因为对它的引用存储在 HttpSession 中。即使 ThreadLocal 中的引用已被清空,在第二次请求期间仍会在会话中找到它。
编辑:在ThreadLocal的OpenJDK源代码中(来自行410) 你可以看到ThreadLocal的set和remove方法之间的区别。调用 set(null) 会将 ThreadLocalMap 条目保留为 null 值,而 remove() 会将其完全删除。对于您的问题来说,这不会产生任何影响,会话中仍然会有对您的 Context 对象的引用。
当我第一次读到你的问题标题时,我有不同的解释,因为没有提到 HttpSession 或清除 ThreadLocal。也许这让一些回复者感到困惑。听起来您想知道第一个请求中设置的 ThreadLocal 变量(且未清除)是否仍然可以在第二个请求中访问。我认为答案是这取决于您的网络服务器如何处理线程。如果线程池中有 10 个随机重用的线程,那么您应该有 10% 的机会在第二个请求中找到相同的 ThreadLocal 变量。
yes, the user will see the Context object because a reference to it was stored in the HttpSession. Even though the reference in the ThreadLocal was nulled, it will still be found in the session during the second request.
EDIT: In the OpenJDK sourcecode of ThreadLocal (from line 410) you can see the difference between ThreadLocal's set and remove methods. Calling set(null) will leave the ThreadLocalMap entry in place with a null value whereas remove() will delete it entirely. It won't make a difference with regard to your question, there will still be a reference to your Context object in the Session.
When I first read your question title I interpreted it differently because there was no mention of the HttpSession or clearing the ThreadLocal. Maybe this confused some of the responders. It sounded like you wanted to know if a ThreadLocal variable set in the first request (and not cleared) would still be accessible in the second request. I think the answer is that this depends on how your webserver handles threads. If there is a threadpool of 10 threads that are randomly reused you should have a 10% chance of finding the same ThreadLocal variable in the second request.
不会。如果您将其设为 null(或者最好调用
threadLocal.remove()
),该值将会丢失。如果不这样做,它可能对于分配了相同线程的下一个请求可见(Servlet 容器使用线程池)。但这是线程池的一个不良副作用——你应该总是清理你的线程局部变量。 (参见此处)
No. If you null it (or better call
threadLocal.remove()
) the value will be lost.If you don't it might be visible to some of the next request to which the same thread is assigned (servlet containers use a thread pool). But this is an undesirable side-effect of thread-pools - you should always clean your threadlocals. (see here)
否 - 除非您使用线程池,否则它将对下一个请求不可见。但是不要将其设置为 null - 最好在线程本地实例上调用remove() - 否则可能会导致内存泄漏。
No - it won't be visible to next request unless you are using a Thread Pool. But instead of making it null - better you call remove() on thread local instance - otherwise you may lead to memory leaks..
这取决于上下文。会话和应用程序上下文被显式恢复,而请求上下文和其他 ThreadLocals 绝对不能依赖于在请求之间持续存在,因为同一个线程可以(并且通常会)处理来自完全不同用户的请求。我相信一些(如果不是全部)Web 容器故意删除所有 ThreadLocal 以避免用户意外共享数据。
That depends on the context. Session and application contexts are explicitly restored, while request contexts and other ThreadLocals can absolutley not be relied upon to persist between requests, since the same thread could (and usually will) handle a request from a completely different user. I believe some (if not all) web containers deliberately delete all ThreadLocals to avoid having users share data accidentally.