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

时间:2021-07-09 00:40:05

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?

所以,如果确实不应该生成线程,那么在需要时执行它的正确方法是什么?

9 个解决方案

#1


81  

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状态有关,从那时起情况有所改善!

#2


32  

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可能会从群集中的一台计算机移动到另一台计算机。线程(以及套接字和其他受限设施)是这种可移植性的重大障碍。

#3


12  

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 this article for details.

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

#4


6  

Concurrency Utilities for 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

这里的例子

#5


2  

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 :)

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

#6


2  

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

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

#7


2  

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

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

But be careful, the bean scopes session and request do not work in threads spawned! Also other code beased on ThreadLocal does not work out of the box, you need to transfer the values to the spawned threads by yourself.

但要小心,bean范围会话和请求在生成的线程中不起作用!另外在ThreadLocal上的其他代码开箱即用,您需要自己将值传递给生成的线程。

#8


1  

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.

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

#9


0  

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,你会遇到问题的一个原因。几乎总有另一种方法可以做一些你不需要线程的事情,所以只说不。

#1


81  

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状态有关,从那时起情况有所改善!

#2


32  

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可能会从群集中的一台计算机移动到另一台计算机。线程(以及套接字和其他受限设施)是这种可移植性的重大障碍。

#3


12  

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 this article for details.

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

#4


6  

Concurrency Utilities for 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

这里的例子

#5


2  

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 :)

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

#6


2  

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

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

#7


2  

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

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

But be careful, the bean scopes session and request do not work in threads spawned! Also other code beased on ThreadLocal does not work out of the box, you need to transfer the values to the spawned threads by yourself.

但要小心,bean范围会话和请求在生成的线程中不起作用!另外在ThreadLocal上的其他代码开箱即用,您需要自己将值传递给生成的线程。

#8


1  

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.

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

#9


0  

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,你会遇到问题的一个原因。几乎总有另一种方法可以做一些你不需要线程的事情,所以只说不。