首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法阻止ExecutorService

无法阻止ExecutorService
EN

Stack Overflow用户
提问于 2014-01-19 12:42:53
回答 2查看 1.7K关注 0票数 0

我试着用executorService.shutdown();结束一个executorService.shutdown();,如果这不起作用,就用executorService.shutdown();。问题是,executorService无法停止,程序仍在运行。

下面是我的类,它将启动一个WatchService来查看目录中的更改:

代码语言:javascript
复制
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 [ stopWatcher() ]1获得了方法1。我编写了一个简单的类来测试FileWatcher类。

代码语言:javascript
复制
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是接口,在这里我得到了所需的更改路径。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-19 13:08:52

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

你正在无限期地循环

代码语言:javascript
复制
    while (!Thread.currentThread().isInterrupted()) {
        key = waitForEvents(watcher, key);
    }

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

如果你改变了

代码语言:javascript
复制
    try {
        key = watcher.take();
    } catch (InterruptedException e) {
        executorService.shutdown();
    } catch (ClosedWatchServiceException e) {
        executorService.shutdown();
    }

代码语言:javascript
复制
    try {
        key = watcher.take();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } catch (ClosedWatchServiceException e) {
        Thread.currentThread().interrupt();
    }

并在while循环之后添加executorService.shutdown(); (或者将其保持在原来的位置),您应该没有问题。

票数 0
EN

Stack Overflow用户

发布于 2014-01-19 12:52:13

如果不分析代码,它就不会关闭,因为任何线程都没有完成/保存资源。简单的脏解决方案是使用ExecuterService.shutdownNow()执行强制停止,它在javadoc中声明:

尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。

因此,尝试这样做,并分析ExecuterService.shutdownNow()返回的Runnable列表,您将返回到查看哪个线程正在挂起,然后一步一步地调试并查看导致挂起的原因。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21216892

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档