Заставить нить спать до установленной даты? - PullRequest
0 голосов
/ 13 февраля 2020

Я хотел знать, как вы можете заставить поток спать до установленной даты, например, до 14 / февраля / 2020.

Тема будет оставаться спящей до этой даты. Есть ли способ сделать это в java?.

Ответы [ 2 ]

1 голос
/ 15 февраля 2020

Служба исполнителя

Определить Runnable (или Callable). Это означает просто наличие run метода для соответствия контракту интерфейса.

В лямбда-синтаксисе:

Runnable runnable =
    () -> { 
        System.out.println( "Looking up fresh stock prices at " + Instant.now().toString() ) ; 
    } 
;

Далее, изучите структуру Executors, встроенную в современный Java. См. Oracle Учебное пособие . Эта структура значительно упрощает сложную работу по планированию потоков.

В частности, вы хотите использовать ScheduledExecutorService. Этот интерфейс предназначен для планирования запуска задачи один раз в определенное время c (фактически, запуск один раз после истечения указанной задержки c), или повторного запуска задачи. Вы, конечно, хотите первое.

Получить реализацию из класса Executors. Для ваших нужд нам нужен только один поток. В других случаях вы можете захотеть использовать пул потоков.

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;

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

Укажите целевую дату. В реальной работе я бы убедился, что дата действительно в будущем.

LocalDate localDate = LocalDate.of( 2020 , Month.FEBRUARY , 23 ) ;

Нам нужен определенный c момент, а не просто дата. Я полагаю, вы хотели бы первый момент этого дня. Не думайте, что это 00:00. Некоторые дни в некоторых зонах в некоторые даты могут начинаться в другое время, например 01:00. Всегда позволяйте java .time определять первый момент.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = localDate.atStartOfDay( z ) ;

Преобразовать из этого часового пояса в UT C.

Instant then = zdt.toInstant() ;

Захватить текущий момент, как показано в UT C.

Instant now = Instant.now() ;

Рассчитайте прошедшее время как Duration.

Duration d = Duration.between( now , then ) ;

Теперь запланируйте выполнение нашей задачи после истечения задержки. Я предлагаю добавить немного времени, чтобы убедиться, что все часы всех связанных систем вписываются в новый день. Плюс полночь, как правило, Час ведьм для вычислений, с большим количеством заданий cron, прокруткой журналов, утилитами и отчетами. Может быть, добавить несколько минут или больше.

ses.scheduleWithFixedDelay( runnable , d.plusMinutes( 7 ).toMinutes() , TimeUnit.MINUTES);

Вы можете захватить возвращенные значения ScheduledFuture для мониторинга вашей задачи.

ВАЖНО Обязательно корректно завершите работу службы исполнителя, если она больше не нужна или когда приложение закрывается. В противном случае ваши потоки могут продолжать работать в фоновом режиме, пережив выход из вашего приложения.

ses.shutdown() ;
0 голосов
/ 13 февраля 2020

Вы можете получить текущую дату с помощью System.currentTimeMillis, получить миллисекунды для данной даты (в вашем случае 14 февраля), вычислить количество миллисекунд, отделяющих текущую дату от данной даты, и вызвать метод sleep (). с этим значением. Честно говоря, я не уверен, каково практическое использование этого.

Вот быстрое решение:

 public static void main(String[] args) {
    long currentMillis = System.currentTimeMillis();
    long givenDateMillis = LocalDateTime.of(2020, 2, 14, 0, 0, 0)
            .atZone(ZoneId.systemDefault())
            .toInstant()
            .toEpochMilli();

    Thread.sleep(givenDateMillis - currentMillis);
}

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

...