Подождите, пока задача завершится, прежде чем завершится в ScheduledThreadPoolExecutor - PullRequest
1 голос
/ 02 февраля 2012

У меня есть реализация 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

Ответы [ 3 ]

1 голос
/ 02 февраля 2012

Самое простое решение - это, так сказать, «чрезмерное обеспечение».Я предлагаю вам использовать огромный период ожидания, который никоим образом не может быть превышен временем, необходимым для выполнения одной задачи, например:

// do you have tasks that can take more than 2^63 - 1 days to finish? :)
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
0 голосов
/ 02 февраля 2012

Как отмечалось в комментарии, 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();
0 голосов
/ 02 февраля 2012

Используйте shutdown(), чтобы начать постепенное завершение, а затем используйте awaitTermination(long, TimeUnit), чтобы дождаться завершения работы службы исполнителя.

...