Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Tomcat Web应用程序中的Spring ThreadPoolTaskExecutor-错误实践?_Spring_Tomcat_Threadpool - Fatal编程技术网

Tomcat Web应用程序中的Spring ThreadPoolTaskExecutor-错误实践?

Tomcat Web应用程序中的Spring ThreadPoolTaskExecutor-错误实践?,spring,tomcat,threadpool,Spring,Tomcat,Threadpool,最近在我的项目中,我需要异步执行一些任务。由于我们在Tomcat中运行一个带有Spring的webapp,Spring提供的ThreadPoolTaskExecutor就是一个解决方案 然而,架构师提出了一些反对意见,指出在webapp中生成线程/拥有线程池是可怕的/禁止的/绝对邪恶的 通过在网络和StackOverflow上搜索一点,我意识到是的,在JavaEE容器中拥有自己的线程池是一种不好的做法。其基本原理是,如果您有自己的线程池,容器就不会知道它,也无法正确管理资源。当您需要对webap

最近在我的项目中,我需要异步执行一些任务。由于我们在Tomcat中运行一个带有Spring的webapp,Spring提供的ThreadPoolTaskExecutor就是一个解决方案

然而,架构师提出了一些反对意见,指出在webapp中生成线程/拥有线程池是可怕的/禁止的/绝对邪恶的

通过在网络和StackOverflow上搜索一点,我意识到是的,在JavaEE容器中拥有自己的线程池是一种不好的做法。其基本原理是,如果您有自己的线程池,容器就不会知道它,也无法正确管理资源。当您需要对webapp进行一些热部署时,这一点尤其重要

现在,我们的用例是在Tomcat中运行的SpringWebApp。首先,我们可以考虑弹簧容器是否像光>强> java EE <强>容器?在这种情况下,是Spring直接管理线程池生命周期,而不是应用程序本身,不是吗

其次,热部署参数是否也适用于此配置

是的,我知道可以直接在Tomcat中声明工作池,并通过JNDI将其注入Spring。但与Spring提供的direct ThreadPoolTaskExecutor工具相比,这有点麻烦

所以我的最后一个问题是:建筑师的反对与我的情况相关吗?


感谢您对本主题的建议和想法。

我认为在Java EE应用程序中拥有自我管理的TaskExecutor是一种不错的做法,如果它被正确隔离的话。将异步任务分离到一个独立的实例中会带来新的复杂性、新的依赖性并降低性能

未管理的架构师参数当然可以为null,因为容器不知道/拥有许多实例(例如静态引用),并且您可以在@Configuration类中或在spring配置文件中配置执行器本身,至少使执行器本身由容器管理

此外,Spring本身公开了几种执行调度方法的方法,例如通过使用@scheduled注释来执行调度方法(http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html)


热部署依赖项取决于您的工作队列的配置方式以及异步任务处理它们的方式。

存在不同级别的邪恶,并且并非所有邪恶都在每种情况下都算作邪恶

按需创建线程而不是使用池通常被认为是邪恶的,但这不仅适用于JavaEE,而且适用于几乎任何类型的服务器应用程序

在JavaEE中,尤其不允许在EJB容器中创建自己的线程。这是因为JavaEE容器可能不可见地将上下文数据存储在线程本地存储中,如果代码开始在自己的线程中执行,则会丢失上下文数据

然而,web容器没有这样的限制,根据规范,拥有线程池或多或少是合法的。例如,这就是为什么人们习惯从EAR中的web模块启动Quartz,即使只使用EJB模块,或者为什么web模块中的代码可以将回调侦听器注册到非托管JMS队列,但EJB无法做到这一点

然而,在实践中,创建线程(通过池)实际上几乎总是可行的,只要您记住,如果您使用例如EJB,您需要在这些线程中运行的代码中从JNDI获取实例,并且不将EJB的引用传递给那些非托管线程。当然,您确实需要注意关闭池,但是JavaEE中几乎每种启动侦听器都有相应的关闭侦听器,您可以在其中执行此操作

Java EE确实有一些官方方法,可以减少创建自己的池的需要:

  • @Asynchronous注释
  • 发送JMS消息并在MDB中处理它
  • 使用
    AsyncContext#start()
    (一般用途有限,请参阅)
  • 使用work manager API(这实际上是供JCA连接器供应商使用的,因此对于最终用户来说不是流线型的,请参阅和)
然而,一些算法需要独立的线程池来防止死锁的可能性。因为没有一个JavaEE解决方案能够绝对保证工作由不同的线程池完成,所以有时候除了创建自己的线程池之外,没有其他可行的方法


因此,在最后一种情况下,将代码向死锁开放实际上比创建自己的线程池更有害。

谢谢马吕斯的反馈。关于热部署,他的论点是,如果我们重新加载webapp,并且容器不知道线程池的存在,那么可能会导致线程在没有引用的情况下四处浮动。我想Spring ThreadPoolTaskExecutor有一个合适的方法或侦听器来拦截容器关闭并正确清理线程,但我不确定。感谢Arjan Tijms提供的非常全面的答案!