Why is spawning threads in Java EE container discouraged?

One of the first things I've learned about Java EE development is that I shouldn't spawn my own threads inside a Java EE container. But when I come to think about it, I don't know the reason.

Can you clearly explain why it is discouraged?

I am sure most enterprise applications need some kind of asynchronous jobs like mail daemons, idle sessions, cleanup jobs etc.

So, if indeed one shouldn't spawn threads, what is the correct way to do it when needed?

55381 次浏览

我从来没有读到过它是令人沮丧的,除了它不容易做正确的事实。

它是相当低级的编程,并且像其他低级技术一样,您应该有一个很好的理由。大多数并发性问题可以通过使用内置构造(如线程池)来更有效地解决。

不应该产生自己的线程的原因是这些线程不会由容器管理。容器处理许多新手开发人员难以想象的事情。例如,线程池、集群、崩溃恢复等操作都是由容器执行的。当你开始一个线程,你可能会失去其中的一些。此外,容器允许您重新启动应用程序,而不会影响它所运行的 JVM。如果有线程不在容器的控制范围内,这怎么可能呢?

这就是从 J2EE 1.4中引入定时器服务的原因。

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

有一些方法可以“正确地”做到这一点,但这取决于所使用的平台。

CommonjWorkManager 对于 WebSphere 和 WebLogic 以及其他应用程序来说是通用的

更多信息请点击这里

还有这里

也有点复制了今天早上的 这个

更新: 请注意,这个问题和答案与 JavaEE 在2009年的状态有关,从那以后情况有所改善!

没有真正的理由不这样做。我使用 石英春天在一个网络应用程序没有问题。还可以使用并发框架 java.util.concurrent。如果您实现了自己的线程处理,将线程头设置为 Deamon或使用自己的守护进程线程组,这样容器可以随时卸载您的 Web 应用程序。

但是要小心,bean 作用域 会议请求不在产生的线程中工作!另外,基于 ThreadLocal的其他代码也不能立即工作,您需要自己将这些值传递给衍生线程。

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

遵守规则,总有一天你会庆幸自己做到了:)

我发现的一个原因是,如果在 EJB 中产生一些线程,然后试图卸载容器或更新 EJB,就会遇到问题。几乎总是有另一种方式来做一些事情,你不需要一个线程,所以只要说不。

对于 EJB 来说,这不仅是不鼓励的,而且是 规格明确禁止的:

企业 bean 不能使用线程 同步原语到 synchronize execution of multiple 例。

还有

企业 bean 不能尝试 to manage threads. The enterprise Bean 不能试图开始,停止, 暂停线程,或恢复线程,或 更改线程的优先级或名称。 企业 bean 不能尝试 管理线程组。

原因在于 EJB 意味着要在分布式环境中操作。EJB 可以从集群中的一台机器移动到另一台机器上。线程(以及套接字和其他受限设施)是这种可移植性的一个重大障碍。

根据蓝图,JavaEE 容器中禁止使用线程。有关详细信息,请参阅 蓝图

JavaEE 并发实用程序

现在有一种标准的、正确的方法来使用核心 JavaEEAPI 创建线程:

通过使用并发实用程序,可以确保创建了新线程,并由容器进行管理,从而保证所有 EE 服务都是可用的。

例子 给你