Событие запускается только один раз при просмотре каталога

использование java.nio наблюдая за сервисом, я пытаюсь посмотреть каталог и все его подкаталоги:

Files.walkFileTree(projectPath, new SimpleFileVisitor<Path>() {
   @Override
   public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        WatchKey key = dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
        watched.put(key, new WatchableDirectory(dir, projectPath));
        return FileVisitResult.CONTINUE;
    }
});

тогда я жду событий:

executor.submit(new Runnable() {
        @Override
        public void run() {
            try {
                WatchKey key;
                while ((key = watcher.take()) != null) {
                    List<WatchEvent<?>> events = key.pollEvents();
                    WatchableDirectory watchableDirectory = watched.get(key);
                    for (WatchEvent<?> event : events) {
                         ....
                    }
             }
          ....
         }
    }

(watched это Map который содержит сопоставления из ключа в метаданные о каталоге)

однако запускается только первое событие для данного каталога. Всякий раз, когда я изменяю другой файл в каталоге, где файл уже был изменен, ничего не происходит (я проверяю это, помещая точка останова и ожидание логики в for-loop).

однако, если я изменяю файл в другом каталоге, то все работает (опять же, только в первый раз).

исключений не возникает (есть предложение catch для java.lang.Exception), и цикл, очевидно, продолжает работать.

Я думал, что, вероятно, после потребления, каталог может быть снят с регистрации. Поэтому я добавил строку для повторной регистрации после обработки файла. Нет эффект.

Windows 7, Java 7.

любые идеи, почему?

1 ответов


не забудьте позвонить

key.reset();

после того, как вы закончите использовать его в своем while петли.

на docs государство

в противном случае, если есть отложенные события для объекта, то эти часы ключ немедленно ставится в очередь к службе наблюдения. Если нет ожидающие события, то ключ watch помещается в состояние готовности и будет оставайтесь в этом состоянии до тех пор, пока не будет обнаружено событие или ключ часов отмененный.

и

ключи вахты безопасны для пользы множественными одновременными потоками. Где существует несколько потоков, извлекающих сигнальные ключи из часов затем следует позаботиться о том, чтобы метод reset был вызывается только после обработки событий для объекта. Этот гарантирует, что один поток обрабатывает события для объекта в любом время.

Так что если вы не сбросите, это как если бы ваш часы отключены.

WatchKey#reset() возвращает логическое значение, если он действует или нет. Обработайте этот случай, как описано в учебник.

Марко подчеркивает:

после того как события для ключа были обработаны, вам нужно положить ключ обратно в состояние готовности, вызвав reset. Если этот метод возвращает false, ключ больше не действителен, и цикл может выйти. Этот шаг очень важно. Если вы не вызовите reset, этот ключ не получит любые дальнейшие события.