Java запустить событие в определенное время в будущем - PullRequest
0 голосов
/ 31 октября 2018

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

Во-вторых, если current_time

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

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

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

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

В 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 Framework , а не устаревший класс Timer. Это особенно верно в среде Servlet или 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, чтобы ее фоновый поток не продолжал весело продолжаться долго после завершения работы вашего веб-приложения.

Джакарта EE

Если в полномасштабном стеке 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 и more .

0 голосов
/ 31 октября 2018

Вы можете использовать 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's 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, для этой цели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...