Rajkishan Swami
Rajkishan Swami

Reputation: 3759

Spring Scheduler threads failing to shutdown in tomcat

I have scheduled tasks that needs to run in a a Web Application deployed on tomcat. I use Spring Boot with Java 8.

What i did,

Configuration Class

@Configuration
@EnableScheduling
class SchedulerConfiguration implements SchedulingConfigurer {

    @ConditionalOnProperty(name = "ScheduleJob1Switch", havingValue = "on")
    @Bean
    FirstScheduledJob firstScheduledJob() {
        return new FirstScheduledJob();
    }

    @ConditionalOnProperty(name = "ScheduleJob2Switch", havingValue = "on")
    @Bean
    SecondScheduledJob secondScheduledJob() {
        return new SecondScheduledJob();
    }

    @Bean(destroyMethod = "shutdown")
    Executor taskExecutors() {
        return Executors.newScheduledThreadPool(10);
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutors());
    }
}

JOB -1

    public class FirstScheduledJob {

    private static final String CLASS_NAME = FirstScheduledJob.class.getName();

    @Autowired
    private SubHandlerDAO subHandlerDAO;

    @Autowired
    private LookupService lookupService;

    @Scheduled(cron = "${FirstScheduledJobCron}", zone = "UTC")
    void firstJob() throws Exception {
       //Do things
    }
}

JOB-2 is also similar

All works fine, except when i try to stop the application. Tomcat log says there are memory leaks for 7-8 threads out of 10 threads i created. Log:

 26-Feb-2016 17:02:04.074 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [sample-job-handler-1.0.0] appears to have started a thread named [pool-1-thread-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.park(Unknown Source)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 java.lang.Thread.run(Unknown Source)

This is the log for one thread. Same Exception for others. Why the destroyMethod="shutdown" on Executor does not work?

Upvotes: 2

Views: 3988

Answers (1)

Rajkishan Swami
Rajkishan Swami

Reputation: 3759

Threads shut down fine if i use, ExecutorService and call its shutdown() in ServletContextListener. Ex:

@Configuration
@EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer {

    /* ............ */

    @Bean(name = "executorService")
    ExecutorService taskExecutors() {
        return Executors.newScheduledThreadPool(10);
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutors());
    }

}

And the Listener,

@Configuration
public class CustomServletContextListener implements ServletContextListener {

    @Autowired
    private ExecutorService executorService;

    @Override
    public void contextInitialized(ServletContextEvent context) {
    }

    @Override
    public void contextDestroyed(ServletContextEvent context) {
        executorService.shutdown();
    }

}

Thanks.

Upvotes: 3

Related Questions