为什么不鼓励在Java EE容器中生成线程?


120

关于Java EE开发的第一件事是,我不应该在Java EE容器中生成自己的线程。但是当我考虑它时,我不知道原因。

您能清楚地解释为什么不鼓励这样做吗?

我确信大多数企业应用程序都需要某种异步作业,例如邮件守护程序,空闲会话,清理作业等。

因此,如果确实不应该产生线程,那么在需要时正确的方法是什么?


4
异步任务通常使用JMS消息传递和MDB完成。
刘坚

5
一旦在容器中实现了JSR 236,这个问题就应该很快成为过去。
letmaik

5
气馁,因为要创建和容器管理的任何第二个线程,因此该线程将有机会获得其他企业资源。使用Java EE7,有一种在企业环境中创建线程的标准且正确的方法。通过使用并发实用工具,可以确保新线程已创建并由容器管理,从而确保所有EE服务均可用。此处的
克里斯·里奇

在JSF / EJB透视图中可以找到几种正确的方法:stackoverflow.com/q/6149919
BalusC

Answers:


84

不建议这样做,因为环境中的所有资源都应由服务器进行管理,并可能由服务器进行监视。同样,使用线程的许多上下文通常都附加到执行线程本身。如果仅启动自己的线程(我相信某些服务器甚至不允许),则该线程将无法访问其他资源。这意味着您无法获得InitialContext,也无法执行JNDI查找来访问其他系统资源,例如JMS连接工厂和数据源。

有一些方法可以“正确”地执行此操作,但这取决于所使用的平台。

commonj WorkManager对于WebSphere和WebLogic以及其他工具都是通用的

更多信息在这里

和这里

也有些重复这个从今天上午

更新:请注意,此问题和答案与2009年Java EE的状态有关,此后情况有所改善!


1
您无法获取InitialContext,也无法执行JNDI查找来访问其他系统资源,例如JMS连接工厂和数据源。我有一个应用程序可以通过在启动线程时注入数据源来解决此问题,但是我可能不得不重新考虑这种方法……
rjohnston 2012年

6
现在有一种使用核心Java EE API创建线程的标准且正确的方法。通过使用并发实用工具,可以确保新线程已创建并由容器管理,从而确保所有EE服务均可用。此处此处的
克里斯·里奇

@ChrisRitchie感谢您的提示。如果仅JBoss AS / IBM WAS支持Java EE 7 ... :-(
asgs 2014年

1
@asgs WildFly 8(JBoss AS的新名称)确实支持Java EE7。IBM只是Java EE 6认证的证书
Chris Ritchie 2014年

34

对于EJB,不仅不鼓励它,而且规范明确禁止它:

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

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

原因是EJB旨在在分布式环境中运行。EJB可能从集群中的一台机器移动到另一台机器。线程(以及套接字和其他受限制的设施)是这种可移植性的重要障碍。


3
Java EE7并发实用程序提供了在企业环境中创建线程的正确方法。此处此处的
克里斯·里奇

1
@Dan您可以向我解释为什么Thread会严重阻碍将EJB从custer中的一台机器移动到另一台机器的可移植性吗?
极客

13

您不应该产生自己的线程的原因是,这些线程不会由容器管理。容器处理了许多新手开发人员难以想象的事情。例如,线程池,群集,崩溃恢复之类的事情由容器执行。启动线程时,您可能会丢失其中一些线程。此外,容器还使您可以重新启动应用程序,而不会影响其运行的JVM。如果有线程超出了容器的控制范围,那怎么可能?

这就是从J2EE 1.4计时器服务引入的原因。请参见文章的详细信息。


2
JSR 236添加了功能来支持Java EE 7和更高版本中的生成线程。请参阅Chris Ritchie的同级回答
罗勒·布尔克


2

您总是可以告诉容器在您的部署描述符中启动东西。然后,它们可以执行您需要执行的任何维护任务。

遵守规则。有一天你会很高兴的:)


2

根据蓝图,在Java EE容器中禁止使用线程。请参考蓝图 以获取更多信息。


2

没有真正的理由不这样做。我在Webapp中将QuarzSpring一起使用时没有问题。也java.util.concurrent可以使用并发框架。如果您实现自己的线程处理,请将theads设置为deamon或为其使用一个自己的deamon线程组,以便容器可以随时卸载您的webapp。

但是要小心,bean作用域会话请求在产生的线程中不起作用!同样,其他代码ThreadLocal无法立即使用,您需要自行将值传输到生成的线程。


1

我从来没有读过它不被劝阻,除非事实是这样做不容易。

这是相当低级的编程,和其他低级技术一样,您应该有充分的理由。使用线程池之类的内置结构,可以更有效地解决大多数并发问题。


7
确实是该规范禁止的。
刘坚

1

我发现如果您在EJB中生成一些线程,然后尝试使容器卸载或更新EJB,您就会遇到问题的原因之一。在不需要线程的情况下,几乎总有另一种方法可以执行某件事,因此只需说“不”即可。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.