2016-12-02 787 views
1

我在写一个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关闭。有人知道我需要为此实现哪个接口?

+0

我真的会用'@ Async'来启动一个普通的旧线程而不是(ab)。和'interrupt()'它基于http://stackoverflow.com/a/6603443/995891 – zapl

回答

0

这是正确的,如果你想要一个非常简单的实现,没有什么更可靠。

使用@Async以更短的任务,它在重新启动等

而且也@Async将保持在每一只腕表顺序激活创建单独的线程,它会压倒线程池和方面是非常有限的能力启动trowing例外,这是相当明显,如果你有长时间运行的任务,因为,

//处理WatchEvents

其他比你的实现是正确的(在我看来)。

一些建议(如果你想使事情变得有趣/复合):

所以,你可以跟踪文件显然是在利用某种持久性机制,引发分离批(可使用Spring Batch)来处理执行并将这些批处理分成一个单独的UI或其他内容,然后您可以在UI上停止,启动和恢复这些批处理过程中的每一个。