停止申请退出时的观察员服务

时间:2017-02-22 18:50:55

标签: java watchservice

我使用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 个答案:

答案 0 :(得分:1)

您的WatcherService课程中需要一个额外的方法,即调用watcher.close()。然后,在WatcherThread课程中,您可以在stopThread()内调用该方法。

WatchService的{​​{3}}中,您可以看到take()一直在等待。您可以通过关闭它来强制完成它。