Java Weblogic线程池中的线程本地安全

Java Weblogic线程池中的线程本地安全,java,jakarta-ee,weblogic,Java,Jakarta Ee,Weblogic,我正在编写一个应用程序,它使用MDB、EJB,并需要ThreadLocal在多个EJB和Helper类之间传递和记录变量,直到事务完成 流程是 从MDB onMessage()开始 ->一些业务代理EJB ->一些助手 问题: 此应用程序在Weblogic中运行,Weblogic重新使用其线程池中的线程。那么,线程之间是否存在数据损坏的可能性?使用ThreadLocal.remove()的解决方案足够安全吗 除了将对象作为参数传递给所有方法之外,还有其他方法替代ThreadLocal吗?当线程返

我正在编写一个应用程序,它使用MDB、EJB,并需要ThreadLocal在多个EJB和Helper类之间传递和记录变量,直到事务完成

流程是

从MDB onMessage()开始 ->一些业务代理EJB ->一些助手

问题:

此应用程序在Weblogic中运行,Weblogic重新使用其线程池中的线程。那么,线程之间是否存在数据损坏的可能性?使用
ThreadLocal.remove()
的解决方案足够安全吗


除了将对象作为参数传递给所有方法之外,还有其他方法替代ThreadLocal吗?

当线程返回池时,WebLogic不会重置用户设置的ThreadLocal变量-用户负责管理这些变量。当这些线程被重用时,它们很可能会产生干扰。由于未清理线程本地引用,您可能会遇到内存泄漏。在将线程返回到容器之前,可以安全地重置线程局部变量。ThreadLocal.remove()调用应该清理它(确保它在finally块中完成)


请注意,如果涉及任何异步或rmi调用,则不会传播线程局部变量。您可能需要考虑WebLogic工作区特性,它允许跨线程、客户机和服务器的上下文传播。有关更多详细信息,请访问

您无法在EJB层中可靠地使用ThreadLocal。即使您的代码现在看起来“工作”,如果有人远程部署您的一个bean,会发生什么?发件人:

为什么不允许创建和管理线程?

EJB规范将责任分配给EJB容器 用于管理线程。允许企业bean实例创建和 管理线程会干扰容器的控制能力 其组件的生命周期。线程管理不是一项业务 函数,这是一个实现细节,通常比较复杂 和平台特定。让容器管理线程可以减轻 处理线程问题的企业bean开发人员。 多线程应用程序仍然是可能的,但是 多线程位于容器中,而不是企业中 豆子


如果需要共享状态,则应将其作为参数传递给EJB方法。这种方法不适合你有什么原因吗?另一种选择是临时将其转储到事务登记数据库或缓存中。

@JoseK:虽然我没有尝试过你在文章中描述的内容,但我的想法如下:-

  • MDB和会话bean都是线程安全的。这意味着,如果有10个bean组成的池,那么只会同时处理10个请求。其他请求将排队等待轮到它们。因此,一个正在运行的线程本地数据不应该干扰另一个线程

  • 如果您有信心在将来也始终使用本地EJB,那么我认为在使用线程本地数据方面没有任何问题。因为您并不是真正在创建线程

  • 虽然weblogic提供了线程池中的线程,但该线程专用于每个请求流,我认为它的本地数据永远不会损坏

  • 正如我所说,我自己没有尝试过,我会尝试的是:-

  • 在MDB层(您的第一层)中,执行Thread.getCurrentThread.setName(名称) 并在后续层中打印线程名称,如thread.getCurrentThread.getName)

    使用不同大小的ejb池、线程池执行多次运行。为每个请求流指定不同的线程名称。尝试同时运行多个请求。看看你有没有把线程名弄混


    5.如上所述,为了使事情更简单和进一步支持远程EJB,我还将CallingContext接口传递给每一层。

    是的,我们的替代方法是将其作为参数传递。但是这个对象需要遍历超过15个方法调用,所以它污染了我们所有的接口和实现。我们希望保持它的非侵入性—它实际上是一个日志对象,由组织强制执行。我不认为只有你一个人这样做,它似乎是一种非常常见的模式。不幸的是,它有点违背了像EJB这样的组件框架的全部目的。毕竟,您并没有向每个方法调用传递事务或安全状态,为什么要传递日志状态?也就是说,如果您选择参数路径,我建议您将这些信息放在一个更健壮的容器中,比如CallingContext对象,并将其传递给其他人。然后,当您需要添加next great thing(tm)时,您不必重构所有接口。