我可以从 MDB 中启动 /spawn 新的 java 线程吗?我需要从 MDB 中的代码进行一些并行处理,然后将控件返回给 MDB。
要求:消息来到 MDB ,然后进行一些代码处理。然后启动两个新的从属线程,它们执行一些并行工作。直到那时 MDB 正在等待。当线程完成工作时。然后控制权返回给MDB,MDB完成相关的final/cleanup工作。
从 MDB 启动一个新线程(Runnable)是个好主意吗?如果不是,那么应该有什么替代方案?
我可以从 MDB 中启动 /spawn 新的 java 线程吗?我需要从 MDB 中的代码进行一些并行处理,然后将控件返回给 MDB。
要求:消息来到 MDB ,然后进行一些代码处理。然后启动两个新的从属线程,它们执行一些并行工作。直到那时 MDB 正在等待。当线程完成工作时。然后控制权返回给MDB,MDB完成相关的final/cleanup工作。
从 MDB 启动一个新线程(Runnable)是个好主意吗?如果不是,那么应该有什么替代方案?
如果您在线程中执行事务性工作,这是一个坏主意。
当前在由 EJB 容器启动的事务中执行工作的线程与事务上下文相关联。在您的情况下,MDB 中的 onMessage 方法会启动一个新事务(除非您指定了 NotSupported 描述符),并且执行此事务的线程将与事务上下文相关联。启动一个新线程,不会将事务上下文传播到子线程。当容器检测到子线程正在尝试访问没有事务上下文的事务资源时,这将导致创建一个新事务。
尽管一些(或大多数?)事务管理器支持拥有相同事务上下文的多个线程的存在,但这可能(并且很可能)不适用于应用程序启动的线程。
从 MDB 启动线程违反了规范。
Enterprise JavaBeansTM,版本 3.0,EJB 核心合同和要求在第 21.1.2 节编程限制中的状态:
企业 bean 不得使用线程同步原语来同步多个实例的执行。
企业 bean 不得尝试管理线程。企业 bean 不得尝试启动、停止、挂起或恢复线程,或者更改线程的优先级或名称。企业 bean 不得尝试管理线程组。
您从根本上忽略了 Java EE 和 MDB 的意义。
Java EE 容器是一个托管的运行时环境。Java EE 容器背后的主要思想是,通过将某些正交关注点(例如事务管理)委托给容器,该组件仍然专注于业务逻辑,并且(在乌托邦中)是一个可重用的组件,对其运行时环境几乎没有假设。
在 MDB 之前,Java EE 容器是一个被动反应式系统,无法协调容器端异步主动代理的操作。Message Driven Beans 随后解决了这个问题,为您在服务器端启动异步操作提供了一种标准方法。
您有一个原始事件e0
被MBD0
. 在消息上,MDB0
将生成e1
一条消息并将其排队以响应MBD1
,然后该消息将完成其工作并将消息发送到MDB2
等。
在那里,您有一个使用pub/sub消息传递语义(以及具有异步语义的 o/c)的 n 个连续步骤的简单工作流,并且所有涉及的线程都由容器管理。如果您希望并发参与者工作,然后收集结果并启动最终操作,请考虑使用涉及 JMS主题的模式。
在 MDB 中启动新线程是不好的做法。它会起作用,但新线程不受应用程序容器的控制,因此可能会出现不可预测的行为。他们甚至会弄乱容器试图维护的线程管理。最糟糕的影响是如果应用程序部署在集群中,那么用户定义的线程将惨遭失败。
在您的场景中:不是启动新线程,而是使用线程逻辑创建新的 MDB(这样它现在将由容器管理),然后将消息发送到这些新的 MDB。如果您希望将控制权返回给父 MDB,那么我认为,请在全局事务中使用您的父 MDB,以便父 MDB 将等待子 MDB 完成并且控制权将返回。