如何从另一个任务中取消 ScheduledFuture 任务并优雅地结束?

How to cancel ScheduledFuture task from another task and end gracefully?

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

这是我的代码:

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刚刚被取消,请问有什么问题吗?

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

Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.

这意味着您需要先调用 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);

在你的情况下,超时永远不会发生,因为你实际上将它设置为 "infinity" 并且当前线程没有被中断。