如何在Spring-Boot中启动(并最终停止)守护进程线程?
问题描述:
我在写一个Spring-Boot应用程序来监视一个目录并处理正在添加的文件。我开始在我的Application
类创建一个ApplicationRunner一个线程调用与@Async
注释的方法:如何在Spring-Boot中启动(并最终停止)守护进程线程?
@SpringBootApplication
@EnableAsync
public class Application {
@Autowired
private DirectoryMonitorService directoryMonitorService;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ApplicationRunner startDirectoryMonitorService() {
return args -> directoryMonitorService.monitorSourceDirectoty();
}
}
这里是DirectoryMonitorService
的代码与@Async
注释的方法:
@Service
public class DirectoryMonitorService {
private static final Logger logger = LogManager.getLogger(DirectoryMonitorService.class);
@Value("${timeout}")
private long timeout;
@Autowired
private WatchService watchService;
@Async
public void monitorSourceDirectoty() {
while (true) {
WatchKey watchKey;
try {
watchKey = watchService.poll(timeout, TimeUnit.SECONDS);
} catch (ClosedWatchServiceException | InterruptedException e) {
logger.error("Exception occured while polling from source file", e);
return;
}
// process the WatchEvents
if (!watchKey.reset()) {
break;
}
}
}
}
终于来了是我在哪里创建的ThreadPoolTaskExecutor:
public class AsyncConfig extends AsyncConfigurerSupport {
private static final Logger logger = LogManager.getLogger(AsyncConfig.class);
private static final String THREAD_NAME_PREFIX = "Parser-";
@Value("${corePoolSize}")
public int corePoolSize;
@Value("${maxPoolSize}")
public int maxPoolSize;
@Value("${queueCapacity}")
public int queueCapacity;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (Throwable ex, Method method, Object... params) -> {
logger.error("Exception message - " + ex.getMessage());
logger.error("Method name - " + method.getName());
for (Object param : params) {
logger.error("Parameter value - " + param);
}
};
}
}
S omehow我觉得这并不是最优雅的启动主线程的方式。有没有人有更好的解决方案?
另外,我宁愿用替代while (true)
与Boolean
变量,我可以设置为false时,Spring-Boot关闭。有人知道我需要为此实现哪个接口?
答
这是正确的,如果你想要一个非常简单的实现,没有什么更可靠。
使用@Async
以更短的任务,它在重新启动等
而且也@Async
将保持在每一只腕表顺序激活创建单独的线程,它会压倒线程池和方面是非常有限的能力启动trowing例外,这是相当明显,如果你有长时间运行的任务,因为,
//处理WatchEvents
其他比你的实现是正确的(在我看来)。
一些建议(如果你想使事情变得有趣/复合):
所以,你可以跟踪文件显然是在利用某种持久性机制,引发分离批(可使用Spring Batch)来处理执行并将这些批处理分成一个单独的UI或其他内容,然后您可以在UI上停止,启动和恢复这些批处理过程中的每一个。
我真的会用'@ Async'来启动一个普通的旧线程而不是(ab)。和'interrupt()'它基于http://stackoverflow.com/a/6603443/995891 – zapl