在Message Driven Bean(MDB)中生成新的java线程

时间:2011-06-07 13:52:30

标签: java multithreading thread-safety ejb message-driven-bean

我可以从MDB中启动/生成新的java线程吗? 我需要从MDB中的代码执行一些并行处理,然后将控制返回给MDB。

要求: 消息来到MDB,然后是一些代码处理。然后启动两个新的从属线程,进行一些并行工作。直到MDB正在等待。当线程完成工作。然后控制返回到MDB,完成相关的最终/清理工作。

从MDB启动新线程(Runnable)是个好主意吗?如果不是那么应该选择什么呢?

4 个答案:

答案 0 :(得分:2)

如果你在线程中执行事务性工作,这是一个坏主意。

当前在EJB容器启动的事务中执行工作的线程与事务上下文相关联。在您的情况下,MDB中的onMessage方法启动一个新事务(除非您指定了NotSupported描述符),并且执行此事务的线程将与事务上下文相关联。启动新线程时,不会将事务上下文传播到子线程。当容器检测到子线程正在尝试访问没有事务上下文的事务资源时,这将导致创建新事务。

虽然一些(或大多数?)事务管理器支持拥有相同事务上下文的多个线程的存在,但这可能(并且很可能)不适用于应用程序启动的线程。

答案 1 :(得分:1)

从MDB启动线程违反了规范。

Enterprise JavaBeansTM,版本3.0,EJB核心合同和要求状态在第21.1.2节编程限制:

  • 企业bean不得使用线程同步原语来同步多个实例的执行。

  • 企业bean不得尝试管理线程。企业bean不得尝试 启动,停止,暂停或恢复线程,或更改线程的优先级或名称。企业bean不得尝试管理线程组。

答案 2 :(得分:1)

您从根本上忽略了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 主题的模式。

答案 3 :(得分:1)

在MDB中启动新线程是不好的做法。它会工作,但新线程不能控制应用程序容器,因此行为不可预测。他们甚至可以搞乱容器试图维护的线程管理。最糟糕的影响是,如果应用程序部署在集群中,那么用户定义的线程将会失败。

在您的场景中:不是启动新线程,而是使用线程逻辑创建新的MDB(这样它现在将由contaner管理)然后向这些新MDB发送消息。如果您希望控件返回到父MDB,我认为,在全局事务中使用您的父MDB,以便父MDB将等待子MDB完成,控件将返回。