2017-02-22 66 views
0

我使用gradleapplication插件來運行監視目錄中更改的應用程序。應用程序退出時停止監視器服務

我的主類看起來像這樣

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(一些包裝過的Java 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()中的該方法。您可以看到take()一直在等待。你可以通過關閉它來強制它完成。

+0

如果我在'stopThread'中調用'close',它會拋出'ClosedWatchServiceException'。 – lapots

+0

的確如此,您可以在代碼中處理與InterruptedException相同的問題。 –

+0

哦,我明白了!謝謝! – lapots

相關問題