2016-12-02 206 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上停止,啓動和恢復這些批處理過程中的每一個。