我尝试使用executorService.shutdown();结束ExecutorService,如果不起作用,请使用executorService.shutdown();结束。问题是,无法停止executorService并且程序仍在运行。

这是我的班级,它将启动WatchService来监视目录中的更改:

public class FileWatcher {
    /**
     * This Class starts a WatchService to get changes on a specific folder.
     */

    Path dir;

    private final ConfigManager configManager;

    private final FileHandler fileHandler;

    private ExecutorService executorService;

    public FileWatcher(ConfigManager configManager, FileHandler fileHandler) {
        this.configManager = configManager;
        this.fileHandler = fileHandler;
    }

    public void start() {
        dir = configManager.getConfig().getJdfPath();

        //executorService = Executors.newFixedThreadPool(1);
        executorService = Executors.newSingleThreadExecutor();
        Runnable runWatcher;
        runWatcher = new Runnable() {
            @Override
            public void run() {
                try {
                    startWatcher();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        executorService.execute(runWatcher);
    }

    private void startWatcher() throws IOException, InterruptedException {
        /**
         * Create a new WatchService which detects created and modified files. To
         * let it detect deleted files add ENTRY_DELETE to dir.register().
         */

        WatchService watcher = FileSystems.getDefault().newWatchService();
        WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_MODIFY);

        while (!Thread.currentThread().isInterrupted()) {
            key = waitForEvents(watcher, key);

        }
    }

    private WatchKey waitForEvents(WatchService watcher, WatchKey key) {

        /**
         * The WatchService tells the FileHandler the Filename of the changed or
         * new file in the given folder.
         */

        try {
            key = watcher.take();
        } catch (InterruptedException e) {
            executorService.shutdown();

        } catch (ClosedWatchServiceException e) {
            executorService.shutdown();

        }

        for (WatchEvent<?> event : key.pollEvents()) {

            fileHandler.setPath((Path) event.context());
        }
        key.reset();
        return key;
    }

    public void stop() {
        stopWatcher();
    }

    private void stopWatcher() {
        executorService.shutdown(); // Disable new tasks from being submitted
        try {
            // Wait a while for existing tasks to terminate
            if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
                executorService.shutdownNow(); // Cancel currently executing tasks
                // Wait a while for tasks to respond to being cancelled
                if (!executorService.awaitTermination(10, TimeUnit.SECONDS))
                    System.err.println("Pool did not terminate");
            }
        } catch (InterruptedException ie) {
            // (Re-)Cancel if current thread also interrupted
            executorService.shutdownNow();
            // Preserve interrupt status
            Thread.currentThread().interrupt();
        }
    }
}


我从oracle java api] 1获得方法stopWatcher()
我编写了一个简单的类来测试FileWatcher类。

public class TestFileWatcher {
    static Path path;
    static ConfigManager configmanager;

    public static void main(String[] args) {

        path = Paths.get("D:/testfolder");
        FileHandler filehandler = new FileHandler() {

            @Override
            public void setPath(Path path) {
                System.out.println("file: " + path);

            }

            @Override
            public Path getPath() {
                // TODO Auto-generated method stub
                return null;
            }
        };

        final Config config;
        config = new Config() {

            @Override
            public Path getJdfPath() {
                // TODO Auto-generated method stub
                return path;
            }
        };

        configmanager = new ConfigManager() {

            @Override
            public void injectConfig(Config config) {
                // TODO Auto-generated method stub

            }

            @Override
            public Config getConfig() {
                // TODO Auto-generated method stub
                return config;
            }
        };



        configmanager.injectConfig(config);
        filehandler.setPath(path);
        final FileWatcher filewatcher = new FileWatcher(configmanager, filehandler);
        filewatcher.start();
        Timer timer = new Timer();


        boolean stopped;

        TimerTask closeWatcherTask = new TimerTask(){
            @Override
            public void run() {

                System.out.println("filewatcher stopped.");
                filewatcher.stop();

            }
        };
        long duration = 2000;
        timer.schedule(closeWatcherTask, duration);
        return;

    }

}


因此,当我启动测试应用程序以启动FileWatcher并在其后2秒钟结束它时,程序将告诉我:Pool did not terminate
我可以更改什么才能正确终止它?

顺便说一下,ConfigManager和FileHandler是接口,在这里我可以获取要更改的路径。

最佳答案

shutDown()仅告诉执行者不接受任何新任务,并取消所有尚未运行的任务。允许正在运行的任务完成。

您无限循环

    while (!Thread.currentThread().isInterrupted()) {
        key = waitForEvents(watcher, key);
    }


因为InterruptedException没有设置中断标志。

如果你改变

    try {
        key = watcher.take();
    } catch (InterruptedException e) {
        executorService.shutdown();
    } catch (ClosedWatchServiceException e) {
        executorService.shutdown();
    }




    try {
        key = watcher.take();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } catch (ClosedWatchServiceException e) {
        Thread.currentThread().interrupt();
    }


并在while循环后添加executorService.shutdown();(或将其保留在原处),应该没有问题。

关于java - 无法停止ExecutorService,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21216892/

10-10 22:52