Как отменить задачу ScheduledFuture из другой задачи и завершить ее изящно?

Я играю с 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 только что отменили, так в чем проблема?


person voho    schedule 23.09.2015    source источник


Ответы (1)


Согласно документу Javadoc ExecutorService.awaitTermination (выделено мной):

Блокируется до тех пор, пока все задачи не завершат выполнение после запроса на завершение работы, или не истечет время ожидания, или текущий поток не будет прерван, в зависимости от того, что произойдет раньше.

Это означает, что вам нужно сначала вызвать 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);

В вашем случае тайм-аут никогда не произойдет, потому что вы практически установили его на «бесконечность», и текущий поток не прерывается.

person Tunaki    schedule 23.09.2015
comment
Спасибо за ваш ответ, это простая заметка в Javadoc, которую я пропустил. Есть ли способ закрыть планировщик после автоматической отмены последней задачи? Или вам нужно где-то держать счетчик и выключать его после того, как он станет равным нулю? - person voho; 24.09.2015
comment
@voho Я не знаю, возможно ли это с помощью ScheduledExecutorService. Взгляните на этот вопрос. - person Tunaki; 24.09.2015