关于Java EE开发的第一件事是,我不应该在Java EE容器中生成自己的线程。但是当我考虑它时,我不知道原因。
您能清楚地解释为什么不鼓励这样做吗?

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

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

评论

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

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

不建议这样做,因为任何第二个线程都应该由容器创建和管理,以便该线程可以访问其他企业资源。使用Java EE7,有一种在企业环境中创建线程的标准且正确的方法。通过使用并发实用程序,可以确保新线程已创建并由容器管理,从而确保所有EE服务均可用。这里的例子

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

#1 楼

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

commonj WorkManager对于WebSphere和WebLogic以及其他工具都是通用的。还从今天早上起重复了这一内容。

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

评论


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

–rjohnston
2012年7月5日在12:53



现在有一种使用核心Java EE API创建线程的标准且正确的方法。通过使用并发实用程序,可以确保新线程已创建并由容器管理,从而确保所有EE服务均可用。这里和这里的例子

–克里斯·里奇(Chris Ritchie)
13-10-16在13:15

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

– asss
14-10-23在4:50

@asgs WildFly 8(JBoss AS的新名称)确实支持Java EE7。IBM仅是Java EE 6认证的认证。

–克里斯·里奇(Chris Ritchie)
14-10-23在11:24

#2 楼

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


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





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


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

评论


Java EE7并发实用程序提供了在企业环境中创建线程的正确方法。这里和这里的例子

–克里斯·里奇(Chris Ritchie)
13-10-16 13:17

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

–极客
2014年6月2日,11:44

#3 楼

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

这就是从J2EE 1.4定时器服务引入的原因。有关详细信息,请参见本文。

评论


JSR 236添加了功能来支持Java EE 7及更高版本中的生成线程。参见克里斯·里奇(Chris Ritchie)的同级回答。

–罗勒·布尔克
16年5月24日在8:09



#4 楼

Java EE的并发实用工具

现在有一种标准的正确方法可以使用核心Java EE API创建线程:



JSR 236: Java™EE

通过使用Concurrency Utils,确保您创建了新线程并由容器进行管理,从而确保所有EE服务均可用。

此处的示例

#5 楼

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

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

#6 楼

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

#7 楼

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

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

#8 楼

我从来没有读过它,因为它不容易正确地进行操作,因此不鼓励使用它。

它是相当低级的编程,并且像其他低级技术一样,您应该具有良好的性能。原因。使用线程池之类的内置结构,可以更有效地解决大多数并发问题。

评论


确实是该规范禁止的。

–刘坚
2010年5月27日下午2:09

#9 楼

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