我学到的关于Java EE开发的第一件事就是我不应该在Java EE容器中生成我自己的线程。但是当我开始思考它时,我不知道原因。
你能清楚地解释为什么气馁吗?
我相信大多数企业应用程序都需要某种异步工作,如邮件守护进程,空闲会话,清理工作等。
因此,如果确实不应该生成线程,那么在需要时执行它的正确方法是什么?
答案 0 :(得分:84)
不鼓励这样做,因为服务器要管理并可能监视环境中的所有资源。此外,正在使用线程的大部分上下文通常附加到执行线程本身。如果您只是启动自己的线程(我相信某些服务器甚至不允许),它就无法访问其他资源。这意味着,您无法获取InitialContext并执行JNDI查找以访问其他系统资源,例如JMS连接工厂和数据源。
有很多方法可以“正确”执行此操作,但这取决于所使用的平台。
The commonj WorkManager is common for WebSphere and WebLogic as well as others
从今天早上开始有点重复this one
更新:请注意,这个问题和答案与2009年的Java EE状态有关,从那时起情况有所改善!
答案 1 :(得分:33)
对于EJB,它不仅气馁,而且明确禁止specification:
企业bean不能使用线程 同步原语到 同步多个执行 实例
和
企业bean不得尝试 管理线程。企业 bean不能试图启动,停止, 暂停,或恢复一个线程,或 更改线程的优先级或名称。 企业bean不得尝试 管理线程组。
原因是EJB旨在在分布式环境中运行。 EJB可能会从群集中的一台计算机移动到另一台计算机。线程(以及套接字和其他受限设施)是这种可移植性的重大障碍。
答案 2 :(得分:12)
您不应该生成自己的线程的原因是容器不会管理这些线程。容器会处理很多新手开发人员难以想象的事情。例如,容器执行线程池,群集,崩溃恢复等操作。当你开始一个线程时,你可能会失去一些。此外,容器还允许您重新启动应用程序,而不会影响它运行的JVM。如果容器的控件中有线程,这怎么可能呢?
这就是引入J2EE 1.4计时器服务的原因。有关详细信息,请参阅this文章。
答案 3 :(得分:7)
现在有一种使用核心Java EE API创建线程的标准且正确的方法:
通过使用Concurrency Utils,您可以确保创建新线程并由容器管理,从而保证所有EE服务都可用。
示例here
答案 4 :(得分:2)
没有真正的理由不这样做。我在webapp中使用Quarz和Spring没有问题。也可以使用并发框架java.util.concurrent
。如果您实现自己的线程处理,请将theads设置为deamon或使用自己的deamon线程组,以便容器可以随时卸载您的webapp。
但是要小心,bean范围 session 和 request 在生成的线程中不起作用!另外,ThreadLocal
上的其他代码无法开箱即用,您需要自己将值传递给生成的线程。
答案 5 :(得分:2)
您始终可以告诉容器启动内容作为部署描述符的一部分。然后,这些可以执行您需要执行的任何维护任务。
遵守规则。有一天你会很高兴:)
答案 6 :(得分:2)
根据蓝图,Java EE容器中禁止使用线程。有关详细信息,请参阅blueprints。
答案 7 :(得分:1)
我从来没有读到这是沮丧的,除非事实并非如此。
这是相当低级的编程,和其他低级技术一样,你应该有充分的理由。使用内置构造(如线程池)可以更有效地解决大多数并发问题。
答案 8 :(得分:1)
我发现如果你在EJB中生成一些线程然后你试图让容器卸载或更新你的EJB会遇到问题的一个原因。几乎总有另一种方法可以做一些你不需要线程的事情,所以只说不。