我正在编写一个Spring-Boot应用程序,监控一个目录并处理添加到其中的文件。我通过在我的Application
类中创建一个ApplicationRunner来启动一个线程,调用一个使用@Async
注解的方法:
@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);
}
};
}
}
我觉得这不是最优雅的启动主线程的方式。有没有更好的解决方案?
另外,我宁愿用一个布尔变量替换 while (true)
,当 Spring-Boot 关闭时我可以将其设置为 false。有人知道我需要实现哪个接口吗?
@Async
。并且根据https://dev59.com/MWw15IYBdhLWcg3wcrdC#6603443中的建议使用`interrupt()`来中断它。 - zapl