如何在Java EE中启动后台进程

11

我想在Java EE(OC4J 10)环境中启动一个后台进程。使用“new Thread”启动线程似乎是错误的做法,但我找不到更好的方式。

在我的特殊情况下,使用JMS队列很困难,因为我的方法调用参数不可序列化。

我还考虑过在会话bean上使用 onTimeout 定时器方法,但这样做不能传递参数(据我所知)。

是否有任何"标准"的方法来处理这样的任务,或者我只能退回到 "new Thread" 或 java.concurrent.ThreadPool

7个回答

14

Java EE通常试图将线程处理从开发者的担忧中移除。(它在这方面的成功是一个完全不同的话题)。

JMS显然是处理这个的首选方法。

对于大多数参数,即使它们默认情况下不可序列化,您也可以选择强制或伪造序列化。根据数据,考虑将其包装在可重新加载数据的可序列化对象中。这显然取决于参数和应用程序。


我不是太喜欢这样做,但我想我会这么做。谢谢。 - ptriller
4
根据具体情况,WorkManager 是首选的方法。它已经在许多应用程序服务器中实现,并允许管理线程的创建。请参考:https://dev59.com/J3RB5IYBdhLWcg3wuZfo - Robin

3
JMS是Java EE实现这一目的的方式。如果容器允许,您可以启动自己的线程,但这会违反Java EE规范(您可能关心或不关心此问题)。
如果您不关心Java EE的通用合规性(如果您实际上会使用线程而不是处理JMS),Oracle容器肯定会有专有的方法来实现这一点(例如 OracleAS作业调度程序)。

1

虽然我不太了解OCJ4,但我在基于Tomcat的应用程序中使用了线程方法和java.util.Timer方法来执行某些任务。在Java 5+中,有一个选项可以使用其中一个Executor服务(Sheduled,Priority)。

我不知道onTimeout是什么,但您可以在会话本身、应用程序上下文或静态变量中传递参数(有些人可能会说这是不鼓励的)。但是名称告诉我它在用户会话超时并且您想要进行一些清理时被调用。


我认为原帖的作者已经了解这一切,他们想知道JavaEE是否提供了官方的方法来实现这一点。JavaEE容器有权禁止创建应用程序级线程,但它并没有提供一个可行的替代方案。 - skaffman
当然,楼主也是这样想的。只是想列举一些在问题中未列出的替代方案。 - akarnokd
如果你想对JMS进行类比,可以使用URLConnection发出HTTP请求到你自己的servlet,该servlet具有你需要执行的操作。这样做很丑陋吗? - akarnokd

1

使用JMS是正确的方法,但它更加重量级。

你得到的优势是,如果你需要多个服务器、一个服务器或任何其他配置,一旦服务器配置完成,你的“线程”现在可以分布到多台机器上。

这也意味着你不想为了微不足道的工作量或大量数据发送消息。选择好你的接口点。


1

1

Java EE并不真正禁止您创建自己的线程,而是EJB规范说“未管理的线程”不允许。原因是这些线程对应用服务器来说是未知的,因此容器无法在这些线程上管理诸如安全性和事务等内容。

尽管如此,有很多框架可以创建自己的线程。例如Quartz、Axis和Spring。改变已经使用其中之一,因此只要您意识到后果,创建自己的线程并不那么糟糕。话虽如此,我同意其他人的观点,即使用JMS或JCA优于手动线程创建。

顺便说一下,OC4J允许您创建自己的线程。但是它不允许从这些未管理的线程中进行JNDI查找。您可以通过指定-userThreads参数来禁用此限制。


我非常清楚这点。如果我在Tomcat或Jetty上部署我的Web应用,我不太关心;但是如果我使用完整的J2EE容器,我会尽量遵守标准,因此我也非常仔细地看待所使用的框架。实际上,这个问题的根源在于我尝试使用Spring Batch而没有启动它自己的线程。如果有选择,这是可以配置的。 - ptriller

0
我来自.NET背景,对我来说JMS似乎相当笨重。相反,我推荐Quartz,这是一个用于Java和JEE应用程序的后台调度库。(我在我的ASP.NET MVC应用程序中使用了Quartz.NET并取得了很大的成功。)

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