Skip to content
Advertisement

Spring Boot async task stuck on shutdown

As per spring documentation for setWaitForTasksToCompleteOnShutdown

Set whether to wait for scheduled tasks to complete on shutdown

Does it mean that if any task is stuck on some long running process and we explicity try to stop the container, it will not be terminated untill that task is finished?

  @Bean
  public TaskExecutor myAsyncTaskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(20);
    executor.setMaxPoolSize(30);
    executor.setQueueCapacity(50);
    executor.setWaitForTasksToCompleteOnShutdown(true); // How it behaves?
    //executor.afterPropertiesSet();
    executor.setThreadNamePrefix("MY-ASYNC-TASK");
    executor.initialize();
    return executor;
  }

Thanks for the answers.

Advertisement

Answer

Short answer? Yes

On shutdown ( either by hitting by a request to the shutdown end point or by calling applicationcontext.close ) by default, Spring’s TaskExecutor simply interrupts all running tasks.

Note that your threads must be in an interruptible state (e.g. sleep) to actually be interrupted.

In some cases you may want to wait for all running tasks to be complete.

calling setWaitForTasksToCompleteOnShutdown(true) simply prevents interrupting the running tasks on shutdown and ensures that both the currently executing tasks and queued up tasks are completed.

( I assume this is because they are non-daemon threads that prevent application exit. )

In short, the answer to your question is yes.

You can play with the following piece of code. When you change setWait from false to true, you will see that the application will not exit until the sleep is over. When you set it to false, the application will terminate immediately.

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;


@SpringBootApplication
public class Application {
    @Autowired
    private TaskExecutor taskExecutor;
    
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(2);
        taskExecutor.setMaxPoolSize(2);
        taskExecutor.setWaitForTasksToCompleteOnShutdown(false);
        taskExecutor.initialize();
        return taskExecutor;
    }
    
    @PostConstruct
    public void runTaskOnStartup() {
        for (int i = 0; i < 1; i++) {
            taskExecutor.execute(() -> {
                try {
                    Thread.sleep(10_000);
                } catch (InterruptedException e) {
                    System.out.println("Sleep Interrupted!");
                    e.printStackTrace();
                }
            });
        }
    }
    
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        run.close();
    }
}
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement