如何在Java EE环境中创建线程?

5

我有一个需求,需要将一些数据保存在表中,由于持久化可能需要一些时间,所以我想要持久化一个日志。但我不希望程序等到持久化完成再继续执行。

我知道我需要使用线程来完成这个任务,但在企业应用程序中创建线程是不被鼓励的。

因此,我开始阅读关于工作管理器的相关资料,并尝试了在websphere应用服务器8.5中编写示例程序。

我使用了来自websphere的asynchbeans.jar,但现在我担心我正在编写特定于供应商的代码。

然后我发现了Oracle Java文档中描述的commonj工作API,并考虑使用fabric3中的commonj API。

我的疑问是,是否有更好的方法来完成相同的任务?例如EJB方法?还是工作管理器对我的要求很好?

3个回答

7

您有几个选择:

  1. 异步bean。这些是供应商特定的,就像您提到的一样。
  2. commonj几乎不是供应商特定的。据我所知,它只被IBM WebSphere Application Server和BEA WebLogic实现。该API已被Java EE并发工具有效取代,这是最好的选择。
  3. EJB @Asynchronous方法。需要使用EJB(对于某些人来说是不必要的复杂性)。
  4. EJB计时器。需要使用EJB,需要可序列化数据。
  5. JMS。可能需要使用MDB接收消息,需要可序列化数据。
  6. 实际创建线程。EE规范不建议这样做,但只要您不尝试使用EE结构(lookup("java:..."),JPA,UserTransaction等),那么您就可以放心使用。

我看到一些代码使用 java.util.concurrent.Executors.newSingleThreadExecutor() 来获取一个 ExecutorService,然后提交一个 Callable 实例。在 Callable 实例的 call 方法中,有一些代码用于将数据持久化到数据库中。这是在 ee 应用程序中有效的方法吗?我想在 Callable 实例中使用 jndi。我可以这样做吗? - Krishna Chaitanya
1
@KrishnaChaitanya,你不能在这样的线程中可靠地使用java:... JNDI查找,并且直接从默认命名空间查找JNDI名称不是Java EE最佳实践。所以,不,不是真的。你最好查找数据源并将其传递给Callable(final local variable或constructor/member variable)。 - Brett Kail
针对6:不可以!根据EJB规范第21.1.2节,企业bean不能尝试管理线程。企业bean不能尝试启动、停止、暂停或恢复线程,也不能更改线程的优先级或名称。企业bean不能尝试管理线程组。任何这样做的企图都将违反EJB规范。 - searchengine27
1
是的,我知道EJB规范上是这么说的,但是我坚持我的观点:有时候手动创建线程是实现目标最快的方式。如果你超出了规范范围,那么需要知道规范提供的服务可能不再适用于你,但有时这仍然是正确的选择。 - Brett Kail

4

实际上,我们正在使用 JEE 6 服务器。 - Krishna Chaitanya

0

如果您需要确保所有日志条目都被安全地写入,则可能应该使用持久消息的JMS。否则,您可以使用@Asynchronous EJB方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接