Оповещения в определённое время Java

320
21 сентября 2017, 14:43

Всем добрый день, хочу сделать так, чтобы действие происходило в определённый момент времени, допустим каждый год 01.01 числа звучала какая-нибудь мелодия. Как так сделать, ведь нельзя же просто загнать всё это дело в отдельный поток с бесконечным циклом, ведь вдруг у меня будет выполнятся по 10 таких проверок одновременно, то это вызовет ужасную нагрузку на процессор. Буду рад, если покажете как это делается, может что-то поновее и получше появилось?)

Answer 1

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

В нем вы сможете создать job'ы и задать парядок выполнения:

 trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(dailyAtHourAndMinute(10, 42))
    .forJob(myJobKey)
    .build();

Данный пример означает, что мы будем запускать нашу задачу ежедневно в 10:42.

Или можно задать более конкретно:

  trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
    .forJob("myJob", "group1")
    .build();

Это означает, что наша задача будет исполняться каждые две минуты ежедневно с 8 утра до 5 вечера.

Преимущество данного подхода в том, что мы не зависим от времени старта и перезапуска приложения. Оно у нас строго фиксировано.

Answer 2

Есть очень классный framework, называется apache camel framework. Суть camel в том, что вы можете быстро и удобно запрограммировать некий маршрут с некоей последовательностью действий. Camel поддерживает кучу компонент и протоколов. Очень много готовых решений.

В вашем случае, требуется, например, компонента apache camel timer, которая запускается с заданной периодичностью и активирует маршрут с заданной последовательностью действий.

То есть будет примерно такой код:

from("timer://foo?fixedRate=true&period=60s")
.bean(MyMelodyRunner);

Где каждые 60 секунд будет запускаться ваш некий класс MyMelodyRunner и запускать bean-метод, в котором вы и напишите свой код, играющий мелодию и/или рассылающий письма :).

Answer 3

Из коробки в Java есть класс ScheduledExecutorService, позволяющий запустить задачу через определенное время или с заданной периодичностью.

ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
// 1 - количество потоков, которые одновременно исполняют задачи

Вы создаете экземпляр задачи:

Runnable task = () -> {
    // ваша задача
};

вычисляете отсрочку для задачи от текущего момента, например в миллисекундах, и закидываете задачу в планировщик:

LocalDate date = LocalDate.of(2017, 12, 1);
long delay = LocalDate.now().until(date, ChronoUnit.MILLIS);
pool.schedule(task, delay, TimeUnit.MILLISECONDS);

При этом вы не гоняете процессор вхолостую и все красиво.

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

Если цель - не повозиться с кодом, а решить задачу, можно посмотреть готовые решения: Quartz, db-scheduler

READ ALSO
Form login с дополнительным полем

Form login с дополнительным полем

Мне нужно добавить в форму авторизации третье поле, но не соображу, как научить Spring Security с ним работатьУ меня пользователи лежат в базе, но кроме...

280
Thinking in Java. Помогите понять задание: part14.project

Thinking in Java. Помогите понять задание: part14.project

ПроектНапишите систему, использующую динамические заместители для реализации транзакций: заместитель закрепляет транзакцию, если опосредованный...

284
Как узнать индекс кнопки при клике

Как узнать индекс кнопки при клике

Есть массив из кнопок

195