我有计划的任务,需要在 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();
}
}
谢谢。