future.cancel(true)不会在ScheduledExecutorService

时间:2016-12-07 07:32:00

标签: java multithreading scheduledexecutorservice

在某些情况下,即使是

的结果,线程也不会停止运行
boolean cancel = future.cancel(true);

是真的。

如果我通过scheduleThread()scheduler

的现有实例添加帖子,则只会发生这种情况

如果我致电schedule()而不是scheduleThread(),那么

if (scheduler != null) {
        List<Runnable> shutdownNow = scheduler.shutdownNow();
    }
    scheduler = Executors.newScheduledThreadPool(elasticsearch2AWSs.size());
    elasticsearch2AWSs.entrySet().forEach(entry -> scheduleThread(entry.getKey(), entry.getValue()));

创建scheduler的新实例并调用scheduleThread()创建一些线程,然后使用future.cancel(true);取消它们一切正常。

但是当我想稍后添加一个线程时,我直接调用scheduleThread(),线程按预期启动,我可以调用future.cancel(true);来阻止它,结果是true但是线程继续运行。我的第一个想法是,它与线程池大小有关,但在这种情况下似乎并不重要。

我在这里缺少什么?任何帮助表示赞赏!

处理线程的ConnectionScheduler

public final class ConnectionScheduler {

    private ScheduledExecutorService scheduler;
    private ConcurrentMap<String, ScheduledFuture<?>> futures = new ConcurrentHashMap<>();

    public void schedule(Map<String, Elasticsearch2AWS> elasticsearch2AWSs) {

        if (scheduler != null) {
            List<Runnable> shutdownNow = scheduler.shutdownNow();
        }
        scheduler = Executors.newScheduledThreadPool(elasticsearch2AWSs.size());
//        scheduler = Executors.newScheduledThreadPool(5); // test purposes

        elasticsearch2AWSs.entrySet().forEach(entry -> scheduleThread(entry.getKey(), entry.getValue()));
    }


    public void scheduleThread(String key, Elasticsearch2AWS elasticsearch2AWS) {
        Map<String, String> awsDimension = elasticsearch2AWS.getAws().get("dimension");
        String dimensionValue = awsDimension.get("value");

        long initialDelay = calcInitialDelay(elasticsearch2AWS.getElasticsearch().get("start"));
        int interval = Integer.valueOf(elasticsearch2AWS.getElasticsearch().get("interval"));
        logger.info("service: {} (start in {} sec and repeats every {} sec)", dimensionValue, initialDelay, interval);

        Runnable task = () -> {
            try {
                logger.info("Runnable task service: {} (start in {} sec and repeats every {} sec)", dimensionValue, initialDelay, interval);
                logger.info("Thread.currentThread().isInterrupted(): {}", Thread.currentThread().isInterrupted());

                elasticConnector.startConnector(elasticsearch2AWS);
            } catch (Exception ex) {
                logger.error("Exception", ex);
            }
        };
        futures.put(key, scheduler.scheduleAtFixedRate(task, initialDelay, interval, TimeUnit.SECONDS)); // filePath is our key

        logger.info("futures '{}'", futures);
    }


    public void stopThread(String key) {
        ScheduledFuture<?> future = futures.remove(key); // remove from our map
        logger.info("stopping task '{}' {}", key, future);
        boolean cancel = future.cancel(true); // cancel the thread
        logger.info("cancel {}", cancel);
        logger.info("futures '{}'", futures);
    }
}

方法watchFolder()在运行时检查修改的文件。如果文件已被修改,则通过connectionScheduler.scheduleThread(file.toString(), loadFile(file)); 启动新线程,即使cancel结果为真,如果取消呼叫,此线程也不会停止。

对于在程序启动时加载的监视文件夹内的现有文件,也会创建线程。此线程可以成功取消,如果我稍后在运行时创建线程,我不知道其中的差异。

public class PropertyReader {
    ...
    public void init() {
        readConfigPropertiesFile();
        readElasticsearchFolder();
        if (thread == null || !thread.isAlive()) {watchFolderThread();}
        connectionScheduler.schedule(elasticsearch2AWSs);
    }

    private void watchFolder() {
        try (final WatchService watchService = FileSystems.getDefault().newWatchService()) {
            foldersToWatch.forEach(path -> path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY));

            while (true) {                
                final WatchKey watchKey = watchService.take();
                for (WatchEvent<?> event : watchKey.pollEvents()) {

                    final Path file = Paths.get(watchKey.watchable() + File.separator + (Path) event.context());

                    if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE || event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) {
                        logger.info("trigger reschedule of task: '{}'", file);
                        elasticsearch2AWSs.put(file.toString(), loadFile(file));
                        connectionScheduler.scheduleThread(file.toString(), loadFile(file));
                        //connectionScheduler.schedule(elasticsearch2AWSs);
                    }
                    if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
                        logger.info("remove task: '{}'", file);
                        connectionScheduler.stopThread(file.toString());
                        elasticsearch2AWSs.remove(file.toString());
                        // TODO remove from executer service
                    }
                }
            }
        } catch (IOException ex) {
            ...
        } 
    }
}

缩短代码以便更好地阅读

0 个答案:

没有答案