【问题标题】:In Java, when ThreadLocal objects are modified, will the changes persist in the next request?在 Java 中,当 ThreadLocal 对象被修改时,更改是否会在下一个请求中持续存在?
【发布时间】:2011-09-05 15:23:18
【问题描述】:

在典型的 Web 应用程序中,当有请求进来时,过滤器会在 http 会话中查找 Context 对象。如果不存在,它会创建 Context 对象并将其存储在 http 会话中。此外,这个 Context 对象也存储在 ThreadLocal 对象中。沿路径的 Servlet 从 ThreadLocal 检索此 Context 对象并对其进行修改。当返回响应时,过滤器现在将 ThreadLocal 中的 Context 对象清空。那么当用户再次发出请求时,是否能够看到修改后的 Context 对象呢?

谢谢 方格

【问题讨论】:

  • 听起来是一个简单的问题,只需尝试一下就可以回答自己,不是吗?

标签: java thread-local


【解决方案1】:

是的,用户将看到 Context 对象,因为对它的引用存储在 HttpSession 中。即使 ThreadLocal 中的引用为空,它仍然会在第二次请求期间在会话中找到。

编辑:在OpenJDK sourcecode of ThreadLocal(来自第 410 行)中,您可以看到 ThreadLocal 的 set 和 remove 方法之间的区别。调用 set(null) 将使 ThreadLocalMap 条目保留为空值,而 remove() 将完全删除它。它不会对您的问题产生影响,Session 中仍然会引用您的 Context 对象。

当我第一次阅读您的问题标题时,我对它的解释有所不同,因为没有提及 HttpSession 或清除 ThreadLocal。也许这让一些响应者感到困惑。听起来您想知道在第一个请求中设置的 ThreadLocal 变量(并且未清除)是否仍然可以在第二个请求中访问。我认为答案是这取决于您的网络服务器如何处理线程。如果有一个随机重用的 10 个线程的线程池,您应该有 10% 的机会在第二个请求中找到相同的 ThreadLocal 变量。

【讨论】:

  • 阿德里安,谢谢。我编写了一个测试程序,并且能够在后续请求中看到修改后的 Context 对象。之前有人指出我需要使用 ThreadLocal.remove() 而不是 ThreadLocal.set(null)。有什么区别?
【解决方案2】:

没有。如果您将其设为空(或更好地调用 threadLocal.remove()),则该值将丢失。

如果您不这样做可能对于分配了相同线程的某些下一个请求是可见的(servlet 容器使用线程池)。但这是线程池的一个不良副作用——你应该总是清理你的线程局部变量。 (see here)

【讨论】:

    【解决方案3】:

    否 - 除非您使用线程池,否则它不会对下一个请求可见。但与其将其设为 null - 最好在线程本地实例上调用 remove() - 否则可能会导致内存泄漏..

    【讨论】:

      【解决方案4】:

      这取决于上下文。会话和应用程序上下文被显式恢复,而请求上下文和其他 ThreadLocals 可以绝对不依赖于在请求之间持续存在,因为同一个线程可以(并且通常会)处理来自完全不同用户的请求。我相信一些(如果不是全部)Web 容器会故意删除所有 ThreadLocal,以避免用户意外共享数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-05
        • 1970-01-01
        • 1970-01-01
        • 2014-04-29
        • 1970-01-01
        • 2014-05-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多