等待任务完成,然后在ScheduledThreadPoolExecutor中终止

时间:2012-02-01 22:17:09

标签: java multithreading concurrency scheduled-tasks

我有一个Runnable实现做了一些可能需要一些时间的工作,我正在尝试使用ScheduledThreadPoolExecutorscheduleAtFixedRate方法安排它。现在我想确保关闭是优雅的,这意味着,在终止之前,应该允许任务完全运行。我已经编写了以下关闭代码。

 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

3 个答案:

答案 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();