在JavaEE EJB / Web容器中创建线程

我在Adam Bien的JavaEE夜间黑客书中读到,虽然EJB容器上禁止创建线程,但Web容器却不是这样。 他实际上在他的X射线探测器中创建了一个线程池执行器,它在Tomcat上运行。

我现在有点困惑。 虽然我遇到了必须在EE应用程序中进行手动线程池管理的情况,但我可以理解为什么在JavaEE容器中手动创建线程是个坏主意。 但是,当您可以将大部分EJB部署到任何一个EJB容器时,我不理解EJB容器和Web容器之间的区别。 如果会话bean在Web容器中生成线程没有任何问题,那么将相同的会话bean部署到EJB容器可能会导致什么问题?

这就是Java EE的“企业”部分与现实世界相遇的地方。

使用“企业”系统的前提主要集中在管理上。 特别是将决策和配置放弃到容器而不是依靠应用程序本身来管理这些资源。 通过将资源的创建和管理与应用程序代码分离并依赖于容器,系统管理员可以查看和访问这些资源,从而有可能在更高级别以通用方式调整和监视应用程序,而不是使用特定于应用程序的机制。

所以,这就是我们所处的环境,而这正是驱动Java EE规范的这些“规则”的一部分,关于你能做什么和不能做什么。

现在,servlet容器规范,更加狂野西部。 它没有所有这些“企业”管理function(介意,许多容器暴露它们,但规范没有提到它们)。 例如,提供静态文件是Web容器的面包和黄油function,因此限制开发人员访问所述文件几乎没有意义。 此外,servlet规范出现在EJB规范之前,并且被绑定到环境中,而不是根据该环境重做。

这给出了两个特定事物(如线程)的“矛盾”规范。

所以,是的,Servlet规范“允许你”管理你自己的线程池,即使在Java EE应用程序中,即使这些线程池可能在完全相同的JVM中(因此“无法管理”消耗Java EE资源) Java EE容器。

在现实世界中,这最终意味着,是的,如果你想,你可以在Java EE容器或servlet容器中整理线程等。 没有一个流行的容器禁止你这样做(WebSphere可能,我不使用它)。

但是,你不应该。 Java EE(特别是Java EE 6)具有机制和箍,您可以跳过来执行操作而不是使用线程池。 诸如WorkManagers,JMS队列,异步会话bean,计时器作业之类的东西。

在servlet应用程序中,大多数这些机制都不存在,因此您无法利用它们,因此您只需使用“Just Java”。

在使用Java EE应用程序部署的Web应用程序中使用“Just Java”的后果是容器内的可见性。 例如,您的Web应用程序将需要自己的配置变量来设置其线程池的大小,并且不能依赖容器来管理它。

最后,它通常是没什么大不了的。 Java EE的大多数复杂性都集中在许多人不使用的管理function上。 对于我自己来说,我使用Java EE并且很少使用普通的WAR,我喜欢尽可能多地将容器推入容器中 – 让它完成它的工作。 也就是说,我在Java EE容器中的WAR中运行自定义套接字服务器,打破了所有可以想象的规则,因为它更容易做到。 “Java EE Way”并不是我们想要完成的任何接近灵活的地方,所以我们选择了“Just Java”并将代码倾注到WAR中,这样我们就可以玩狂野西部了,男人就是男人和男人。管理自己的线程。

EJB由服务器管理。 管理意味着dependency injection。 如果使用注释从类生成线程,则服务器将无法处理它们(执行@PostConstruct,注入引用等)。

EJB始终在EJB容器中执行,因此不应在EJB中手动创建线程。 即使它们是作为WAR文件(Web模块)的包,它们也在EJB容器中执行,并且对于线程创建具有相同的限制。

但是,servlet和filter在Web容器中执行,并且没有任何东西禁止它们拥有自己的手动管理的线程池。