2009-02-10 86 views
108

我对Java EE开发的第一件事就是我不应该在Java EE容器中产生自己的线程。但是当我想到这个问题时,我不知道原因。为什么不鼓励Java EE容器中的产卵线程?

你能否清楚地解释为什么不鼓励?

我相信大多数企业应用程序需要某种像邮件守护进程,空闲会话,清理工作等异步作业的

所以,如果确实不应该产生线程,是什么做的正确方法需要的时候?

+4

异步任务通常使用JMS消息传递和MDB完成。 – 2010-05-27 02:14:01

+5

在容器中实现[JSR 236](http://jcp.org/en/jsr/detail?id=236)后,此问题应该很快成为过去。 – letmaik 2013-08-04 16:17:43

+4

因为任何第二个线程都应该由容器创建和管理,所以该线程将有权访问其他企业资源,因此不鼓励它。使用Java EE7,在企业环境中创建线程是一种标准且正确的方法。通过使用Concurrency Utils,您可以确保您的新线程已创建并由容器管理,从而确保所有EE服务都可用。 示例[here](http:// stackoverflow。COM /问题/ 3212255/Java的EE规格和 - 多线程在JSF/EJB角度/ 19404307#19404307) – 2013-10-22 08:21:54

回答

79

因为环境中的所有资源都是由服务器管理并可能受到监控,所以不鼓励它。此外,线程正在使用的上下文的大部分内容通常会附加到执行线程本身。如果你只是开始自己的线程(我相信一些服务器甚至不允许),它不能访问其他资源。这意味着,您无法获得InitialContext并执行JNDI查找来访问其他系统资源,如JMS连接工厂和数据源。

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

The commonj WorkManager is common for WebSphere and WebLogic as well as others

More info here

And here

也有些重复this one从今天上午

更新:请注意,这个问题和答案涉及到Java EE的状态,2009年的事情从那以后有了改进!

1

我从来没有读过它,因为它不容易做到正确这一事实,所以不鼓励它。

这是相当低级的编程,和其他低级技术一样,你应该有一个很好的理由。大多数并发问题可以使用内置结构(如线程池)更有效地解决。

+7

是确实被规范禁止。 – 2010-05-27 02:09:45

11

你不应该产生自己的线程的原因是这些不会被容器管理。容器处理了许多新手开发人员难以想象的事情。例如,线程池,集群,崩溃恢复等事情由容器执行。当你开始一个线程时,你可能会失去一些线程。该容器还允许您重新启动应用程序,而不会影响其运行的JVM。如果线程超出容器的控制范围,这将如何实现?

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

2

没有真正的理由不这样做。我在网上应用中使用了QuarzSpring,没有任何问题。也可以使用并发框架java.util.concurrent。如果您实现自己的线程处理,请将方块设置为deamon或为它们使用自己的deamon线程组,以便容器随时卸载web应用程序。

但要小心,豆的范围会话请求不能在线程中产生!此外,ThreadLocal上的其他代码无法正常工作,您需要自行将值传输到衍生线程。

2

你总是可以告诉容器启动东西作为部署描述符的一部分。这些可以做任何你需要做的维护任务。

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

0

我发现的一个原因是,如果你在你的EJB中产生了一些线程,然后你尝试让容器卸载或更新你的EJB,你将遇到问题。几乎总是有另一种方式去做一些你不需要线程的东西,只是说NO。

32

对EJB来说,它不仅是气馁,它明确的禁止specification

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

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

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

2

根据蓝图,Java EE容器中禁止线程。请参阅blueprints了解更多信息。

5

并发工具为Java EE

现在有一个标准,并建立与核心Java EE API螺纹的正确方法:

通过使用并发utils的,你确保你的新线程被创建并由容器管理,保证所有的EE服务都可用。

示例here