ScheduledExecutorService
Вы можете использовать класс ScheduledExecutorService
( документация ), который доступен с Java 5. Он даст ScheduledFuture
( документация *)1009 *), который можно использовать для контроля выполнения и его отмены.
В частности, метод:
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
, который
Представляет одинзадача, которая становится активной после заданной задержки.
Но вы также можете посмотреть другие методы, в зависимости от фактического варианта использования (scheduleAtFixedRate
и версий, принимающих Callable
вместо * 1023).*).
Начиная с Java 8 (Streams, Lambdas, ...) этот класс становится еще более удобным благодаря доступности простых методов преобразования между старым 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 .(Хотя это не имеет большого значения для этого приложения, оно просто чище).