2017-02-22 7 views
0

Я использую плагин gradle и application для запуска приложения, которое следит за изменениями в каталоге.служба стоп-часов в приложении quit

Мой главный класс выглядит следующим образом

public static void main(String[] args) throws IOException { 
    WatcherThread thread = new WatcherThread(EXTENSION_FOLDER); 
    thread.start(); 

    try(BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) { 
     String input = null; 
     ConsoleInputController controller = new ConsoleInputController(br); 
     while (!QUIT_COMMAND.equals(StringUtils.trim(input))) { 
      System.out.println(CONSOLE_TEMPLATE); 
      System.out.println("input (to exit write [quit]):> "); 

      input = br.readLine(); 
      controller.handleInput(input); 
     } 
    } catch (IOException exc) { 
     LOGGER.error("Failed to process input.", exc); 
    } 

    thread.stopThread(); 
} 

WatcherThread класс нить, которая использует WatcherService (некоторые обертку над WatchService Явы)

public class WatcherThread extends Thread { 
    private static final Logger LOGGER = LoggerFactory.getLogger(WatcherThread.class); 

    private boolean watch = true; 
    private WatcherService watcherService; 

    public WatcherThread(String searchingPath) throws IOException { 
     watcherService = new WatcherService(Paths.get(searchingPath)); 
    } 

    @Override 
    public void run() { 
     LOGGER.info("Artifact watching thread started."); 
     while(watch) { 
      if (!watcherService.watch()) { 
       break; 
      } 
     } 
     LOGGER.info("Artifact watching thread stopped."); 
    } 

    public void stopThread() { 
     watch = false; 
    } 
} 

WatcherService выглядит следующим образом

public class WatcherService { 
    private static final Logger LOGGER = LoggerFactory.getLogger(WatcherThread.class); 

    private final WatchService watcher; 
    private final Map<WatchKey, Path> keys; 
    private boolean trace; 

    WatcherService(Path dir) throws IOException { 
     watcher = FileSystems.getDefault().newWatchService(); 
     keys = new HashMap<>(); 

     register(dir); 

     trace = true; 
    } 

    private void register(Path dir) throws IOException { 
     WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); 
     if (trace) { 
      Path prev = keys.get(key); 
      if (null == prev) { 
       LOGGER.info("Register path: [{}].", dir); 
      } else { 
       if (!dir.equals(prev)) { 
        LOGGER.info("Updated path: [{}] -> [{}].", prev, dir); 
       } 
      } 
     } 
     keys.put(key, dir); 
    } 

    boolean watch() { 
     WatchKey key; 
     try { 
      key = watcher.take(); 
     } catch (InterruptedException exc) { 
      return false; 
     } 

     Path dir = keys.get(key); 
     if (null == dir) { 
      LOGGER.warn("WatchKey is not recognized!"); 
      return false; 
     } 

     // forEach? 
     for (WatchEvent event: key.pollEvents()) { 
      LOGGER.info("Polling events"); 
      WatchEvent.Kind kind = event.kind(); 
      if (OVERFLOW == kind) { 
       continue; 
      } 

      WatchEvent<Path> ev = (WatchEvent<Path>) event; 
      Path name = ev.context(); 
      Path child = dir.resolve(name); 

      LOGGER.info("Event occurred [{}] in [{}].", event.kind().name(), child); 
      WatchEventResolver.resolveEvent(ev, child); 
     } 

     boolean valid = key.reset(); 
     if (!valid) { 
      keys.remove(key); 

      if (keys.isEmpty()) { 
       return false; 
      } 
     } 

     return true; 
    } 
} 

Когда я не start мой WatcherThread - консольный ввод работает нормально. Я могу quit, например, без проблем. Но когда я запускаю поток и хочу выйти, он ждет пару секунд, а затем заканчивается.

Насколько я понимаю, это что-то с WatchService, которое не может остановить просмотр каталога.

Как остановить его на quit заявление немедленно?

ответ

1

Похоже, что вам нужен дополнительный метод в вашем классе WatcherService, который звонит по номеру watcher.close(). Затем в классе WatcherThread вы можете вызвать этот метод внутри stopThread().

В Javadoc для WatchService вы можете видеть, что take() продолжает ждать. Вы можете заставить его закончить, закрыв его.

+0

Хорошо, что он выбрасывает 'ClosedWatchServiceException', если я назову' close' в 'stopThread'. – lapots

+0

Точно, тогда вы можете обрабатывать его так же, как 'InterruptedException' в вашем коде. –

+0

О, я вижу! Благодаря! – lapots