【问题标题】:How to cancel ScheduledFuture task from another task and end gracefully?如何从另一个任务中取消 ScheduledFuture 任务并优雅地结束?
【发布时间】:2015-12-20 20:24:45
【问题描述】:

我在玩ScheduledExecutorService。我想要做的是启动一个简单的ticker(每秒一个tick)并稍后安排另一个任务(五秒后)取消第一个任务。然后阻塞主线程直到一切都完成,这应该是在两个任务完成之后(+- 5 秒)。

这是我的代码:

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Runnable tickTask = () -> System.out.println("Tick");
ScheduledFuture<?> scheduledTickTask = executor.scheduleAtFixedRate(tickTask, 0, 1, TimeUnit.SECONDS);
Runnable cancelTask = () -> scheduledTickTask.cancel(true);
executor.schedule(cancelTask, 5, TimeUnit.SECONDS);
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

让我吃惊的问题是它会阻塞,就好像还有一些正在运行的任务一样。为什么? cancelTask 应该立即结束,而 scheduledTickTask 刚刚取消,那么问题出在哪里?

【问题讨论】:

    标签: java multithreading java-8 scheduled-tasks scheduledexecutorservice


    【解决方案1】:

    根据 ExecutorService.awaitTermination 的 Javadoc(强调我的):

    阻塞,直到所有任务完成执行关闭请求后,或发生超时,或当前线程被中断,以先发生者为准。

    这意味着您需要先致电shutdown,如下所示:

    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    Runnable tickTask = () -> System.out.println("Tick");
    ScheduledFuture<?> scheduledTickTask = executor.scheduleAtFixedRate(tickTask, 0, 1, TimeUnit.SECONDS);
    Runnable cancelTask = () -> {
        scheduledTickTask.cancel(true);
        executor.shutdown();
    };
    executor.schedule(cancelTask, 5, TimeUnit.SECONDS);
    executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
    

    在您的情况下,超时永远不会发生,因为您实际上将其设置为“无限”并且当前线程没有被中断。

    【讨论】:

    • 感谢您的回答,这是我错过的 Javadoc 中的一个简单注释。有没有办法在最后一个任务自动取消后关闭调度程序?或者您必须在某处保留一个计数器并在它为零后关闭?
    • @voho 我不知道这是否可以使用ScheduledExecutorService。看看this question
    猜你喜欢
    • 1970-01-01
    • 2012-09-19
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-11
    • 2013-05-05
    • 1970-01-01
    相关资源
    最近更新 更多