为什么不鼓励在 Java EE 容器中生成线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/533783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:55:21  来源:igfitidea点击:

Why is spawning threads in Java EE container discouraged?

javamultithreadingjakarta-ee

提问by LiorH

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.

我学到的关于 Java EE 开发的第一件事是我不应该在 Java EE 容器中生成自己的线程。但是当我想到它时,我不知道原因。

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?

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

采纳答案by Robin

It is discouraged because all resources within the environment are meant to be managed, and potentially monitored, by the server. Also, much of the context in which a thread is being used is typically attached to the thread of execution itself. If you simply start your own thread (which I believe some servers will not even allow), it cannot access other resources. What this means, is that you cannot get an InitialContext and do JNDI lookups to access other system resources such as JMS Connection Factories and Datasources.

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

There are ways to do this "correctly", but it is dependent on the platform being used.

有多种方法可以“正确”执行此操作,但这取决于所使用的平台。

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

commonj WorkManager 对 WebSphere 和 WebLogic 以及其他人来说是通用的

More info here

更多信息在这里

And here

和这里

Also somewhat duplicates this one from this morning

从今天早上开始也有点重复这个

UPDATE: Please note that this question and answer relate to the state of Java EE in 2009, things have improved since then!

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

回答by levand

I've never read that it's discouraged, except from the fact that it's not easy to do correctly.

我从来没有读过它是不鼓励的,除了因为它不容易正确执行这一事实。

It is fairly low-level programming, and like other low-level techniques you ought to have a good reason. Most concurrency problems can be resolved far more effectively using built-in constructs like thread pools.

这是相当低级的编程,与其他低级技术一样,您应该有充分的理由。使用线程池等内置结构可以更有效地解决大多数并发问题。

回答by kgiannakakis

The reason that you shouldn't spawn your own threads is that these won't be managed by the container. The container takes care of a lot of things that a novice developer can find hard to imagine. For example things like thread pooling, clustering, crash recoveries are performed by the container. When you start a thread you may lose some of those. Also the container lets you restart your application without affecting the JVM it runs on. How this would be possible if there are threads out of the container's control?

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

This the reason that from J2EE 1.4 timer services were introduced. See thisarticle for details.

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

回答by Arne Burmeister

There is no real reason not to do so. I used Quarzwith Springin a webapp without problems. Also the concurrency framework java.util.concurrentmay be used. If you implement your own thread handling, set the theads to deamonor use a own deamon thread group for them so the container may unload your webapp any time.

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

But be careful, the bean scopes sessionand requestdo not work in threads spawned! Also other code beased on ThreadLocaldoes not work out of the box, you need to transfer the values to the spawned threads by yourself.

但是要小心,bean 作用域会话请求在产生的线程中不起作用!此外,其他基于代码的代码ThreadLocal也无法开箱即用,您需要自己将值传输到生成的线程。

回答by Thorbj?rn Ravn Andersen

You can always tell the container to start stuff as part of your deployment descriptors. These can then do whatever maintainance tasks you need to do.

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

Follow the rules. You will be glad some day you did :)

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

回答by Javamann

One reason I have found if you spawn some threads in you EJB and then you try to have the container unload or update your EJB you are going to run into problems. There is almost always another way to do something where you don't need a Thread so just say NO.

我发现的一个原因是,如果您在 EJB 中生成一些线程,然后尝试卸载容器或更新您的 EJB,您将会遇到问题。在不需要线程的情况下,几乎总是有另一种方法可以做一些事情,所以只需说不。

回答by Dan Dyer

For EJBs, it's not only discouraged, it's expressly forbidden by the specification:

对于 EJB,不仅不鼓励这样做,而且规范明确禁止这样做:

An enterprise bean must not use thread synchronization primitives to synchronize execution of multiple instances.

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

and

The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread's priority or name. The enterprise bean must not attempt to manage thread groups.

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

The reason is that EJBs are meant to operate in a distributed environment. An EJB might be moved from one machine in a cluster to another. Threads (and sockets and other restricted facilities) are a significant barrier to this portability.

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

回答by Ojitha

Threads are prohibited in Java EE containers according to the blueprints. Please refer to the blueprintsfor more information.

根据蓝图,Java EE 容器中禁止使用线程。请参阅蓝图以获取更多信息。

回答by Chris Ritchie

Concurrency Utilities for Java EE

Java EE 的并发实用程序

There is now a standard, and correct way to create threads with the core Java EE API:

现在有一种标准且正确的方法来使用核心 Java EE API 创建线程:

By using Concurrency Utils, you ensure that your new thread is created, and managed by the container, guaranteeing that all EE services are available.

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

Examples here

这里的例子