@Scheduled Tasks keep JVM hanging when standalone

2019-07-17 09:20发布

问题:

i opened this bug in the spring bug tracker. would be cool if some clever people here can already help me

https://jira.springsource.org/browse/SPR-9341

回答1:

Set "true" on daemon property for the scheduler - eg

<!-- task scheduling for @Scheduled annotation -->
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="1" />

<bean id="myScheduler" class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
    <property name="poolSize" value="2" />
    <property name="threadNamePrefix" value="myScheduler-"/>
    <property name="waitForTasksToCompleteOnShutdown" value="false" />
    <property name="daemon" value="true" />
</bean>


回答2:

Have you tried having your @Scheduled bean implement DisposableBean (so it can be informed when the Spring context is shutting down) and explicitly closing the context in your main() method?

Conceptually, I don't see how the code posted can work like you expect. Spring needs to launch new threads to run your @Scheduled task at the time/rate you configure, which means that when the code in your main() method exits, there are non-daemon threads still running in the JVM. If you don't tell Spring to shut these threads down, then how will they be terminated?

edit: to be clear, I think the solution is to explicitly call close() on your ApplicationContext. Otherwise Spring does not have a way to tell the executor service running your scheduled tasks to shut itself down. A JVM shutdown hook will not be invoked when main() exits since non-daemon threads are still running.



回答3:

This is the solution using Java config

@Bean
public TaskScheduler daemonTaskScheduler() {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setDaemon(false);
    taskScheduler.setThreadNamePrefix("daemon");
    taskScheduler.setPoolSize(5);
    return taskScheduler;
}

or if you want to really get into the details, the config class can be like this

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {

   @Override
   public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

One thing is not supported though is to be able to use multiple TaskSchedulers within a single application. I opened a JIRA for that