【问题标题】:ThreadLocal usage in enterprise application企业应用程序中的 ThreadLocal 使用
【发布时间】:2012-05-06 21:26:14
【问题描述】:

如果我的 web 应用程序和 ejb 应用程序在同一台机器上(在同一 JVM 上)并且所有 ejb 调用都是本地调用,那么在将信息从 web 传递到 ejb 时使用ThreadLocal 会产生任何问题吗?

如果 ejb 调用是远程的,有什么解决方法吗? ThreadLocal 信息是否可以从 Web 应用程序到 ejb 应用程序?在这种情况下是否建议使用ThreadLocal

【问题讨论】:

    标签: java jakarta-ee ejb thread-local


    【解决方案1】:

    对于第一个问题,只要在每次调用结束时去掉 ThreadLocal 变量就没有问题。这很重要,因为容器(servlet 或 ejb)通常使用线程池并因此重用线程,这有两个影响:一个“调用”可能会看到来自先前调用的线程本地信息,以及如果您在不停止 JVM 的情况下从容器中删除应用程序有些类可能不会被垃圾收集,因为它们仍然被容器线程引用。因此,将数据放在 try / finally 块中的 threadlocal 中,并在 finally 部分中删除。

    这里有一篇文章展示了解决问题的一种方法:ThreadLocal in web applications

    对于第二个问题,因为数据是线程本地的,它不会伴随远程调用,您必须在接口中添加一个参数,在一侧提取线程本地数据并在另一侧重新创建它...

    【讨论】:

    • 谢谢。基本上是在为现有的 ee 应用程序添加多语言功能,而无需修改大部分代码。我将在 HTTP 会话中设置语言信息,然后在 HTTP 会话中使用该信息来在“ThreadLocal”中设置值。因此必须在每个请求之前调用应用程序中的一个位置(可能是 HTTPFilter),并从 HTTPSession 设置“ThreadLocal”中的值。这将确保它在 EJB 中可用,最终作为数据库参数传递给它。
    • 这将确保即使我不删除它,它也会被每次覆盖。谢谢你的回答。
    【解决方案2】:

    使用 EJB 3.1 时,您可以使用 context dataEJBContext 中传递上下文信息。这只是一个Map<String,Object>

    【讨论】:

      【解决方案3】:

      ThreadLocal 不应在 EJB 上下文中使用。不能保证 EJB 方法调用都在同一个线程上(当然应该如此)。

      在 EJB 中有一个不同的方法调用 TransactionSyncrhonizationRegistry。详情请见Explanation/Usage

      【讨论】:

        【解决方案4】:

        所有的ejb调用都是本地调用,会不会使用ThreadLocal创建 期间的任何问题

        不,你自己回答了你的问题。由于调用是本地的,它们在一个线程的上下文中执行。

        如果 ejb 调用是远程的,有什么解决方法吗?

        在远程调用的情况下,Java EE 容器将在另一个 JVM 中运行,它会产生自己的线程来处理传入的 RMI 请求,远程 Java EE 容器无法知道线程局部变量在另一边被宣布。将其作为参数对象传递。

        【讨论】:

          【解决方案5】:

          这取决于你传递什么信息!第一个问题太笼统了。我建议阅读与 ThreadLocal here 相关的 JavaDoc。

          ThreadLocal 来自应用程序的服务器端,用于让线程安全地调用 Thread 对象。

          【讨论】:

          • ThreadLocal 的 javadoc 还远远不够。您不确定服务器将如何管理线程、将它们绑定到请求等。
          【解决方案6】:

          对于本地调用,ThreadLocal 应该可以正常工作,只要一切都在同一个线程中完成。

          对于可能在不同服务器上运行的远程调用,您将需要想出其他方法。将所有值作为参数传递(这将起作用,但会在代码中引入复杂性)或使用分布式缓存之类的东西,例如Hazelcast,其功能类似于全局 HashMap,所有集群节点都可以访问。

          【讨论】:

            【解决方案7】:

            ThreadLocal 不能在 Web 应用程序中 100% 确定地使用。您根本无法保证一个线程将用于一个会话。在我看来,这很难找到安全漏洞!

            ctx.getContextData() 对我不起作用,它总是返回 null

            我也尝试了TransactionSynchronizationRegistry,但我也得到了null

            唯一可行的方法是使用 JAAS 作为解决方法。但这不是一个好的解决方案。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-04-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-07-26
              相关资源
              最近更新 更多