Java запустить событие в определенное время в будущем

0

Я проектирую веб-приложение на Java с использованием трикотажа, в котором у меня есть поле даты и времени, "future_time" в mysql db. У меня также есть поле состояния в той же таблице, установленное в ожидании. Я хочу обновить поле статуса до завершенного в дБ, если текущее время> = future_time. Как будто я хочу запланировать событие.

Во-вторых, если current_time <future_time и если я обновил значение future_time, я бы хотел перенести предыдущее событие.

В настоящее время всякий раз, когда я получаю поле состояния, я проверяю, ожидает ли оно ожидания, ожидает ли оно, тогда я проверяю, находится ли future_time <= current_time, если так, тогда я обновляю поле состояния в db до завершенного. Но в этом есть проблема. Это только обновит поле состояния, когда я получу его. Поэтому, если я получу поле состояния через долгое время (после future_time), оно будет обновлено в тот момент, сохраняя неправильные записи в дБ.

Может кто-нибудь предложить мне лучший способ достичь этого?

  • 3
    Возможно, используйте планировщик, либо стандартный по умолчанию из Java, либо, если вы не возражаете против другой зависимости, используйте Quarz.
  • 0
    Есть ли другой способ вместо планировщика?
Показать ещё 1 комментарий
Теги:
web-services
web
jersey

2 ответа

0

Рассчитать истекшее время до истечения срока

В JDBC 4.2 и более поздних версиях извлекайте дату и время, используя современные классы java.time.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class );  // Likely to be a UTC value.

Получить текущий момент.

OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC ) ;

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

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

Расписание мероприятия

Используйте современную среду Executor, а не унаследованный класс Timer. Это особенно верно в среде сервлетов или Jakarta.ee(Java EE).

Определите вашего исполнителя, в частности, ScheduledExecutorService. Нам нужна только одна нить для этой задачи.

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor()

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

myExecutorService.schedule(           // Tell the executor what you want to run, and when you want it run on your behalf in a background thread.
    new Runnable() { … } ,            // Define task to be executed as a 'Runnable'.
    d.toSeconds() ,                   // Amount of time to wait until execution. Use self-documenting code rather than a "magic number" such as '86400000'. 
    TimeUnit.SECONDS                  // Specify the granularity of time used in previous pair of arguments.
)                                     // Returns a 'ScheduledFuture' which you may want to cache.

При желании вы можете захватить ScheduledFuture возвращаемое этим оператором schedule. Затем вы можете отслеживать статус завершения.

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

Сервлет веб-контейнер

Для веб-контейнера сервлета, такого как Tomcat или Jetty без полного стека Jakarta.ee, применимо приведенное выше обсуждение.

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

Джакарта Э.

Если в полномасштабном стеке Jakarta.ee, таком как Glassfish, эта работа намного проще.

Описанная выше услуга для исполнителя может быть автоматизирована с настройкой и демонтажем от вашего имени. Используйте утилиты параллелизма, определенные в JSR 236. Утилиты параллелизма для JavaTM EE. Это было рассмотрено много раз, поэтому ищите переполнение стека для получения дополнительной информации.


О java.time

Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытеснять неприятные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, и SimpleDateFormat.

Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.

Чтобы узнать больше, смотрите Oracle Tutorial. И поиск для многих примеров и объяснений. Спецификация JSR 310.

Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*.

Где взять классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и другие.

  • 0
    Если это выполняется в веб-контейнере сервлета, есть ли способ сохранить информацию о запланированном событии, чтобы я мог отменить ее при необходимости? Или, как вы упомянули, единственный способ сделать это - просто проверить состояние записи в момент запуска события?
  • 0
    @theyuv Прочитайте класс JavaDoc и обратите внимание, что метод schedule возвращает ScheduledFuture , как упомянуто в моем Ответе. Используйте этот объект для контроля завершения и отмены, если это необходимо.
Показать ещё 4 комментария
0

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

Вы можете создать ScheduledExecutorService как:

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

А затем используйте сервис для планирования заданий, таких как:

//scheduling at fixed time.
Future<String> resultFuture = executorService.schedule(new Callable<String>() {
    @Override
    public String call() throws Exception
    {
        //your code;
    }
}, 1, TimeUnit.SECONDS);

//scheduling at fixed intervals.
executorService.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run()
    {
        //your code
    }
}, 100, 450, TimeUnit.MILLISECONDS);

//scheduling at fixed delays.
executorService.scheduleWithFixedDelay(new Runnable() {
    @Override
    public void run()
    {
        //your code
    }
}, 100, 150, TimeUnit.MILLISECONDS);

Вы также можете использовать Java Timer Utility для планирования задач на будущее, но спецификация Java говорит, что предпочтительнее ScheduledExecutorService. Ниже приведен пример кода для планирования заданий с помощью таймера.

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;


/**
 * An example for Java Timer Utility.
 *
 * @author Karan Khanna.
 */
public class TimerExample
{

    public static void scheduleTaskForFuture(final Date date)
    {
        Timer timer = new Timer("Timer");
        TimerTask task = new TimerTask()
        {
            public void run()
            {

                System.out.println(
                    String
                        .format("Task performed on: %s and Thread name: %s", date, Thread.currentThread().getName()));

                timer.cancel();
            }
        };
        timer.schedule(task, date);
    }



    public static void main(final String[] args)
    {
        Calendar calendar = new GregorianCalendar();
        calendar.add(Calendar.MINUTE, 1);
        TimerExample.scheduleTaskForFuture(calendar.getTime());
    }
}

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

Для этой цели вы также можете попробовать другие фреймворки, такие как Quartz и Spring.

  • 1
    Документация для Timer рекомендует вместо этого использовать среду Executor .
  • 0
    @BasilBourque Добавлен фреймворк для исполнителя.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню