4

我有 ThreadPoolTask​​Executor。我应该发送太多电子邮件(不同的电子邮件)。如果在电子邮件发送过程中出现错误,我应该将其写入数据库。

<bean id="taskExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="5" />
    <property name="maxPoolSize" value="10" />
    <property name="WaitForTasksToCompleteOnShutdown" value="true" />
</bean>

我正在执行任务。taskExecutor.execute(可运行)。一切正常!

@Override
public void run() {
    try {
        mailService.sendMail();
    } catch (Throwable t) {
        daoService.writeFaillStatus();
    }
} 

一切似乎都很好!异步请求做得很好!

我也有

  white(true) { 
    if(executor.getActiveCount()==0){
       executor.shutdown(); break;
     }
      Thread.sleep(3000)
    }

因为 WaitForTasksToCompleteOnShutdown=true 任务永远不会被自动关闭。换句话说,主线程永远不会被破坏(主线程是我调用线程执行器任务的线程 - 当我在 eclipse 中运行代码时,终端始终处于活动状态)。即使在执行程序线程完成他们的工作之后,我的控制台也看起来像这样:在此处输入图像描述

我认为这是因为,主线程正在等待某些东西——有人说“一切都已经完成,放松,去关闭”

所以想到了这个解决方案while(true)。你能告诉我这是否是个好主意吗?可能是不好。

我知道这个执行器也有 submit() 方法。我想我不需要这里。如果我在这篇文章中不正确,请纠正我。

4

2 回答 2

11

因为您使用的是 Spring ThreadPoolTaskExecutor,所以您很幸运。

如果您配置以下内容,它将允许您指定在强制关闭之前等待的秒数。

<bean id="taskExecutor"
     class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="5" />
    <property name="maxPoolSize" value="10" />
    <property name="WaitForTasksToCompleteOnShutdown" value="true" />
    <property name="awaitTerminationSeconds" value="X" />
</bean>

将 X 的值设置为您希望进程在终止前等待的秒数。

从文档中awaitTerminationSeconds

如果“waitForTasksToCompleteOnShutdown”标志设置为 true,它将继续完全执行所有正在进行的任务以及队列中的所有剩余任务,同时关闭容器的其余部分。在任何一种情况下,如果您使用此属性指定等待终止期,则此执行程序将等待给定时间(最大值)以终止任务。根据经验,如果同时将“waitForTasksToCompleteOnShutdown”设置为 true,请在此处指定显着更高的超时时间,因为队列中的所有剩余任务仍将执行 - 与默认关闭行为相反,它只是等待当前正在执行的任务对线程中断没有反应。

基本上,您正在尝试强制执行应该由框架单独处理的事情。由于特殊情况,它应该是决定何时关闭任务执行器的框架。我会删除你所有试图关闭任务执行器的代码,并在你所有的工作完成后让 Spring 处理关闭。然后 Spring 也会正确关闭 main。

于 2015-03-13T03:04:49.950 回答
3

如果您事先知道有多少是“太多电子邮件”,我建议您查看CountDownLatch而不是繁忙的等待循环来检查任务状态。

在主线程中设置

CountDownLatch latch =  new CountDownLatch(TOO_MANY_EMAILS);

将此实例传递给可运行实例,我们latch.countDown()在发送每封邮件后调用该实例。

在主线程中,我们等待闩锁倒计时:latch.await(). 这将阻止主线程执行。

之后,您可以在知道所有工作已完成的情况下安全地关闭线程池。

于 2015-03-13T05:58:14.097 回答