ScheduledExecutorService
Вы можете использовать ScheduledExecutorService
(documentation), который доступен начиная с Java 5. Он даст ScheduledFuture
(документация), которую можно использовать для отслеживания выполнения, а также для его отмены.
В частности, метод:
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
который
Отправляет одноразовую задачу, которая становится доступной после заданной задержки.
Но вы также можете изучить другие методы, в зависимости от фактического варианта использования (scheduleAtFixedRate
и версии, принимающие Callable
вместо Runnable
).
Начиная с Java 8 (потоки, лямбда-выражения, ...) этот класс становится еще более удобным благодаря наличию простых методов преобразования между старым TimeUnit
и более новым ChronoUnit
(для вашего ZonedDateTime
), а также возможности предоставления Runnable command
как лямбда или ссылка на метод (потому что это FunctionalInterface
).
Пример
Давайте посмотрим на пример, выполняющий то, что вы просите:
// Somewhere before the method, as field for example
// Use other pool sizes if desired
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
public static ScheduledFuture<?> scheduleFor(Runnable runnable, ZonedDateTime when) {
Instant now = Instant.now();
// Use a different resolution if desired
long secondsUntil = ChronoUnit.SECONDS.between(now, when.toInstant());
return scheduler.schedule(runnable, secondsUntil, TimeUnit.of(ChronoUnit.SECONDS));
}
Вызов прост:
ZonedDateTime when = ...
ScheduledFuture<?> job = scheduleFor(YourClass::yourMethod, when);
Затем вы можете использовать job
для наблюдения за выполнением, а также отменить его, если хотите. Пример:
if (!job.isCancelled()) {
job.cancel(false);
}
Примечания
Вы можете заменить параметр ZonedDateTime
в методе на Temporal
, тогда он также принимает другие форматы даты/времени.
Не забудьте выключить ScheduledExecutorService
, когда закончите. В противном случае у вас будет запущен поток, даже если ваша основная программа уже завершена.
scheduler.shutdown();
Обратите внимание, что мы используем Instant
вместо ZonedDateTime
, поскольку информация о зоне не имеет для нас значения, если разница во времени вычисляется правильно. Instant
всегда представляет время в формате UTC, без каких-либо странных явлений, таких как DST. (Хотя это не имеет особого значения для этого приложения, оно просто чище).
person
Zabuzard
schedule
06.03.2019