WatchService неправильно опрашивает - PullRequest
0 голосов
/ 22 ноября 2018

Я хотел бы опрашивать каталог каждые 10 секунд, чтобы увидеть, были ли какие-либо файлы добавлены или изменены.Если в течение 10 секунд произошли какие-либо изменения, я хотел бы получить набор всех путей к файлам, которые затем можно будет передать другому методу.

Проблема

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

Пример
Я создал полный пример, который просматривает каталог.Затем поток ожидает 5 секунд и копирует 2000 файлов в просматриваемый каталог.
Ожидаемое поведение для WatchService - проверка изменений каждые 10 секунд.Вместо этого, похоже, мгновенно накапливаются изменения.

Код

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;

public class DirectoryWatcherExample 
{
    private static final int POLLING_TIME = 10;

    public static void main(final String args[]) throws InterruptedException, IOException
    {
        final Path directory = Paths.get("directory/to/be/watched");

        /**
         * Start a thread that will create 2000 files to the selected directory
         * This will occur after waiting 5 seconds.
         */
        new Thread(new Runnable()
        {
            @Override
            public void run() 
            {
                try 
                {
                    Thread.sleep(5000);         
                    System.out.println("Copying 2000 files to directory: " + directory);
                    for(int i = 0; i < 2000; i++)
                    {
                        final PrintWriter writer = new PrintWriter(directory.resolve("test_file_" + i + ".txt").toFile(), "UTF-8");
                        writer.println("The first line");
                        writer.println("The second line");
                        writer.close();
                    }
                    System.out.println("Finished copying files to directory: " + directory);
                } 
                catch (final Exception e) 
                {
                    e.printStackTrace();
                } 
            }
        }).start();

        /**
         * Start the watch service polling every 10 seconds
         */
        new DirectoryWatcherExample().startWatchService(directory);
    }

    public void startWatchService(final Path directory) throws InterruptedException, IOException
    {
        final WatchService watchService = FileSystems.getDefault().newWatchService();
        directory.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY);

        while(true)
        {
            System.out.println("Start polling");
            final WatchKey key = watchService.poll(POLLING_TIME, TimeUnit.SECONDS);
            System.out.println("Finished polling and retrieved key");

            if(key != null)
            {
                final Collection<Path> paths = new HashSet<>();
                for (final WatchEvent<?> watchEvent : key.pollEvents())
                {
                    final Path path = ((Path) key.watchable()).resolve((Path) watchEvent.context());
                    paths.add(path);
                    System.out.println("Path added: " + path);
                }

                // Do something with the paths
                addedFiles(paths);

                if (!key.reset())
                {
                    break;
                }   
            }

        }
    }

    // Unimplemented
    public void addedFiles(final Collection<Path> paths)
    {

    }
}

Что может быть причиной этого?

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Существует два варианта:

  1. Вам необходимо вызвать poll на watchService после определенного интервала, поспав между ними.Как отмечали другие, время ожидания в методе poll предназначено для сценариев, когда в буфере нет доступных событий.Кроме того, поскольку вы не обрабатываете события сразу, некоторые из них могут переполнить буфер операционной системы и в конечном итоге потеряться.Следовательно, вам также необходимо обработать сценарий переполнения.

  2. В качестве альтернативы вы можете использовать библиотеку Apache Commons IO File Monitoring.Он опрашивает файловую систему, как вы хотите.Вы даже можете установить интервал опроса.

См. Следующие три класса / интерфейса здесь :

  • FileAlterationMonitor - Это в основном поток (a Runnableреализации), который спит в течение интервала опроса и после каждого интервала вызывает FileAlterationObserver
  • FileAlterationObserver - в нем перечислены файлы в каталоге, сравнивается текущий список с предыдущим списком, идентифицируются изменения файла и вызываетсясоответствующий метод в реализации FileAlterationListener
  • FileAlterationListener - интерфейс, который вам нужно реализовать и написать свою логику

Что вы можете сделать для своего варианта использования, так это сохранитьдобавление всех деталей файла в список по мере их добавления или изменения.Наконец, когда вызывается метод onStop(), вы вызываете ваш метод addedFiles с полным списком, очищаете список и начинаете снова.

0 голосов
/ 22 ноября 2018

Параметр времени ожидания в WatchService.poll(timeout, unit) не предназначен для определения продолжительности задержки.Он только определяет максимальное время ожидания (после этого он возвращает, было ли обнаружено событие или нет.)

Он все еще возвращается, как только обнаружил изменение.Считайте JavaDoc для WatchService.poll

Извлекает и удаляет следующий ключ наблюдения, ожидание, если необходимо, до указанного времени ожидания, если его еще нет.

Нигде не написано, что он всегда будет ждать так долго.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...