Java Timer: как использовать классы для работы со временем

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

Портрет программиста

Таймер и таски в Java

Классы Timer и TimerTask находятся в пакете java.util и предназначены для планирования выполнения задач. Timer отвечает за расписание, а TimerTask - это собственно задача, которая будет выполняться.

Чтобы использовать таймер, нужно создать экземпляр класса Timer:

Timer timer = new Timer();

А затем создать задачу, расширяя класс TimerTask и переопределяя метод run():

 class MyTask extends TimerTask { public void run() { // код задачи } } 

В методе run() пишем код, который должен выполниться в назначенное время.

Чтобы запустить выполнение, вызываем метод schedule() у таймера, передав в него экземпляр задачи:

 MyTask task = new MyTask(); timer.schedule(task, 1000); 

Здесь задача запустится через 1000 миллисекунд.

Внутри run() можно получить время выполнения задачи через scheduledExecutionTime():

 public void run() { long time = scheduledExecutionTime(); // время запуска в миллисекундах } 

Рассмотрим простой пример таймера, который выводит сообщение через 5 секунд:

 class MessageTask extends TimerTask { @Override public void run() { System.out.println("Сообщение из таска!"); } } public class Main { public static void main(String[] args) { Timer timer = new Timer(); MessageTask task = new MessageTask(); timer.schedule(task, 5000); } } 

После запуска через 5 секунд в консоли появится "Сообщение из таска!".

Таким образом, Timer и TimerTask позволяют удобно выполнять задачи в фоновом потоке через заданный промежуток времени. Далее рассмотрим более сложные варианты использования.

Серверная комната

Однократный запуск таймера

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

Запуск таска в указанное время

Чтобы запланировать задачу на конкретный момент, используем перегруженный метод schedule(), который принимает объект Date:

 Date startTime = ...; // дата и время запуска timer.schedule(task, startTime); 

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

Создадим задачу DatabaseMigrationTask:

 class DatabaseMigrationTask extends TimerTask { private List<String> oldDatabase; private List<String> newDatabase; public DatabaseMigrationTask(List<String> oldDb, List<String> newDb) { this.oldDatabase = oldDb; this.newDatabase = newDb; } public void run() { // копируем данные из oldDatabase в newDatabase } } 

И запланируем ее выполнение, например, на завтрашнюю ночь в 2 часа:

 Date startTime = ...; // 02.03.2023 2:00 Timer timer = new Timer(); DatabaseMigrationTask task = new DatabaseMigrationTask(oldDb, newDb); timer.schedule(task, startTime); 

Таким образом задача запустится точно в назначенное время.

Ожидание запуска таска

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

 while(Date.now().before(startTime)) { // таск еще не запущен } 

Пока текущее время меньше запланированного, таск точно не начал выполняться.

Таким образом, Timer позволяет гибко планировать однократное выполнение задач в Java. Далее рассмотрим варианты с периодическим запуском.

Периодический запуск таймера

Для регулярного выполнения задач Timer предоставляет методы schedule() и scheduleAtFixedRate(). Рассмотрим их подробнее.

Повторение с фиксированной задержкой

Метод schedule() позволяет указать период запуска в миллисекундах. Например, чтобы повторять каждые 5 секунд:

 timer.schedule(task, 0, 5000); 

Здесь задача сначала запустится без задержки (0 мс), а затем будет повторяться каждые 5 секунд.

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

Повторение с фиксированной частотой

Метод scheduleAtFixedRate() позволяет запускать задачи строго по расписанию, независимо от длительности предыдущего запуска.

Например, расписание на каждые 5 секунд:

 timer.scheduleAtFixedRate(task, 0, 5000); 

Теперь, если задача выполняется дольше 5 секунд, следующий запуск все равно произойдет через 5 секунд после предыдущего по расписанию.

Какой режим выбрать, зависит от конкретной задачи. Для быстрых операций разница несущественна. Но при длительных задачах scheduleAtFixedRate() помогает избежать накопления задержек.

Рассмотрим пример использования таймера для ежедневной задачи, например, автоматической проверки обновлений и отправки уведомления:

 class DailyUpdateCheckTask extends TimerTask { @Override public void run() { // проверка обновлений // отправка уведомления } } Timer timer = new Timer(); long delay = 0; long period = 1000 * 60 * 60 * 24; // 1 день timer.scheduleAtFixedRate(new DailyUpdateCheckTask(), delay, period); 

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

Таким образом, Timer предоставляет гибкие возможности для планирования периодических задач в Java. Далее рассмотрим варианты остановки выполнения таймеров.

Статья закончилась. Вопросы остались?
Комментарии 0
Подписаться
Я хочу получать
Правила публикации
Редактирование комментария возможно в течении пяти минут после его создания, либо до момента появления ответа на данный комментарий.