我有一个Runnable
实现做了一些可能需要一些时间的工作,我正在尝试使用ScheduledThreadPoolExecutor
和scheduleAtFixedRate
方法安排它。现在我想确保关闭是优雅的,这意味着,在终止之前,应该允许任务完全运行。我已经编写了以下关闭代码。
public void shutDown() throws Exception {
try {
LOG.info("Gracefully shutting down executor");
executor.shutdown();
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
// cancels currently executing tasks.
LOG.info("Executor is still alive. Forcing executor thread pool to shut down");
executor.shutdownNow();
// Wait a while for tasks to respond to being cancelled
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
LOG.fatal("Executor thread pool did not terminate");
throw new Exception("Unable to shut down executor thread pool forcefully");
}
LOG.info("Executor shut down.");
}
} catch (Exception e) {
LOG.error("Exception shutting down executor", e);
throw e;
}
}
但问题是,我必须指定明确等待的时间,我无法提前预测任务所花费的时间。有没有办法使执行程序无限期地等待,直到执行任务完成而不必提及等待时间?或者有更好的方法来处理上述情况吗?
由于
Jitendra
答案 0 :(得分:1)
最简单的解决方案就是“过度配置”。我建议你使用一个巨大的超时时间,单个任务执行所需的时间决不会超过,例如:
// do you have tasks that can take more than 2^63 - 1 days to finish? :)
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
答案 1 :(得分:0)
使用shutdown()
开始正常终止,然后使用awaitTermination(long, TimeUnit)
等待执行程序服务完成关闭。
答案 2 :(得分:0)
正如评论executor.shutdown()
中所指出的那样,并没有强制任何任务退出,而是阻止新的任务被接受。请查看javadoc。
另一个建议是,如果你想在完成任务后立即掌握你的任务,你可以实现Callable<T>
而不是Runnable
它是泛型类型并返回类型为T的值然后,您可以将此Callable<T>
打包到FutureTask<V>
并将其提交给ScheduledThreadPoolExecutor
。然后,您可以在完成工作并完成任务后立即循环完成任务。所以简而言之就是这样(一旦我们完成了对任务加载调度程序的通知,就可以安全地关闭它,这意味着我们不允许从那时起提交任何其他任务):
ScheduledExecutorService schedulerExecutor = Executors.newScheduledThreadPool(n);
Callable<Integer> myTask = . . .;
FutureTask<Integer> task = new FutureTask<Integer>(myTask);
schedulerExecutor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
schedulerExecutor.shutdown();