为什么不鼓励Java EE容器中的产卵线程?

我从Java EE开发中学到的第一件事就是我不应该在Java EE容器中产生自己的线程。 但是当我思考的时候,我不知道原因。

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

我相信大多数企业应用程序需要某种asynchronous作业,如邮件守护进程,空闲会话,清理作业等。

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

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

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

commonj WorkManager对于WebSphere和WebLogic以及其他人来说都很常见

更多信息在这里

和这里

今天早上还有些重复

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

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

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

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

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

你不应该产生自己的线程的原因是这些不会被容器pipe理。 容器照顾了很多新手开发者难以想象的东西。 例如,线程池,集群,崩溃恢复是由容器执行的。 当你开始一个线程时,你可能会失去一些线程。 此外,容器可以让您重新启动您的应用程序,而不会影响它运行的JVM。 如果线程超出容器的控制范围,这将如何实现?

这是从J2EE 1.4定时器服务引入的原因。 详情请参阅这篇文章。

Java EE的并发实用程序

现在有一个标准的,正确的方法来创build核心Java EE API的线程:

  • JSR 236:用于Java™EE的并发实用程序

通过使用Concurrency Utils,确保您的新线程由容器创build并pipe理,从而保证所有EE服务都可用。

这里的例子

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

按照规则。 你会很高兴有一天你做:)

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

没有真正的理由不这样做。 我在没有任何问题的情况下使用了Spring的 Quarz 。 也可以使用并发框架java.util.concurrent 。 如果你实现了自己的线程处理,把它们设置为deamon或者为它们使用自己的deamon线程组,这样容器可以在任何时候卸载你的webapp。

但要小心,bean作用域会话请求不会在线程中产生! 此外, ThreadLocal上的其他代码无法正常工作,您需要自行将值传递给生成的线程。

我从来没有读过这样的话,除非事情做起来不容易。

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

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