Spring Scheduler线程无法在tomcat中关闭

时间:2016-02-26 11:42:45

标签: java multithreading spring-mvc tomcat spring-boot

我已安排需要在tomcat上部署的Web应用程序中运行的任务。我在Spring 8中使用Spring Boot。

我做了什么,

配置类

@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也类似

一切正常,除非我试图停止申请。 Tomcat日志说我创建的10个线程中有7-8个线程存在内存泄漏。经度:

 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)

这是一个线程的日志。其他人也有同样的例外。 为什么destroyMethod="shutdown" Executor不起作用?

1 个答案:

答案 0 :(得分:0)

如果我使用ExecutorService并在shutdown()中调用ServletContextListener,则线程会关闭。例如:

@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());
    }

}

和听众,

@Configuration
public class CustomServletContextListener implements ServletContextListener {

    @Autowired
    private ExecutorService executorService;

    @Override
    public void contextInitialized(ServletContextEvent context) {
    }

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

}

感谢。