Перезапустить тему с просмотром папки - PullRequest
0 голосов
/ 24 ноября 2018

У меня есть нить, которая просматривает папку, установленную в файле настроек.Если я изменю настройки, я бы хотел остановить поток и начать новый поток с актуальной папкой для просмотра.Этот код работает нормально, но появляется сообщение об ошибке.

public static void resetWatch() throws FileNotFoundException, IOException, InterruptedException {
    BufferedReader setup = new BufferedReader(new FileReader(new File("setup\\setup.dat")));
    String DirtoWatch = setup.readLine();

    Path toWatch = Paths.get(DirtoWatch);
    if(toWatch == null) {
        throw new UnsupportedOperationException("Directory not found");
    }

    // make a new watch service that we can register interest in
    // directories and files with.
    myWatcher = toWatch.getFileSystem().newWatchService();

    // start the file watcher thread below
    fileWatcher = new Watcher(myWatcher, toWatch);

    th = new Thread(fileWatcher, "FileWatcher");
    th.start();
    System.out.println("Monitoring " + DirtoWatch + " for changes...");
    // register a file
    toWatch.register(myWatcher, ENTRY_CREATE);
    th.join();
}

Класс Watcher

public class Watcher implements Runnable {

    private WatchService myWatcher;
    public Path path;
    private WatchKey key;

    public Watcher(WatchService myWatcher, Path path) {
        this.myWatcher = myWatcher;
        this.path = path;
    }

    @Override
    public void run() {
        String evCon;

        try {
            // get the first event before looping
            key = myWatcher.take();
            while(key != null) {

                for (WatchEvent event : key.pollEvents()) {
                    evCon =  event.context().toString();
                    System.out.println("New file: " + evCon);
                    Thread.sleep(500);
                    folder_changed(path.toString() + "/" + evCon);
                }
                key.reset();
                key = myWatcher.take();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException ex) {
            Logger.getLogger(Watcher.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Stopping thread");
    }

    public void stopThread() {
        try {
            System.out.println("Closing the ws");
            myWatcher.close();
            if(key!=null) {
                key.cancel();  
            }
            Thread.currentThread().interrupt();
        } catch (IOException | ClosedWatchServiceException exc) { System.out.println("Closing thread exception"); }
    }
}

И если я изменяю настройки, я обновляю файл установки, а затем пытаюсь закрыть Watcher и снова запустить поток:

try{
        fileWatcher.stopThread();
        myWatcher.close();
    }
    catch(ClosedWatchServiceException | IOException ex) { System.out.println("Watch Service exc. "); } 

    try {
        resetWatch();
    } catch (IOException | InterruptedException ex) { System.out.println("Recall resetWatch exc. "); }

Тогда он "работает", но я получаю следующее исключение, указывающее на ключ наблюдения:

Monitoring ..path.. for changes...
Closing the ws
Monitoring ..path.. for changes...
Exception in thread "FileWatcher" java.nio.file.ClosedWatchServiceException
Recall resetWatch exc. 
    at sun.nio.fs.AbstractWatchService.checkOpen(AbstractWatchService.java:80)
    at sun.nio.fs.AbstractWatchService.checkKey(AbstractWatchService.java:92)
    at sun.nio.fs.AbstractWatchService.take(AbstractWatchService.java:119)
    at jstockcheck.Watcher.run(Watcher.java:40)
    at java.lang.Thread.run(Thread.java:748)

Есть предложения, как избежать этих ошибок?Спасибо!

1 Ответ

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

Метод close может быть вызван в любое время для закрытия службы, в результате чего любые потоки, ожидающие получения ключей, выдают ClosedWatchServiceException.

ClosedWatchServiceException - если эта служба наблюдения закрыта, илион закрывается во время ожидания следующего ключа.

В вашем случае, я думаю, это просто вопрос перехвата исключения, когда вызывается take, и обработки его в режиме без вывода сообщений, например:

try {
    key = myWatcher.take()
} catch (ClosedWatchServiceException e) {
    continue;
}

Это согласно: https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html

...