Spring 调度程序线程无法在 tomcat 中关闭



我有计划的任务,需要在 tomcat 上部署的 Web 应用程序中运行。我在Java 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());
    }
}

作业 -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 日志说我创建的 7 个线程中有 8-10 个线程存在内存泄漏。日志:

 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)

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

如果我使用,线程会关闭正常,ExecutorService并在ServletContextListener中调用其shutdown()。前任:

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

谢谢。

最新更新