Введение в кварц
1. Обзор
Кварцевый — это структура планирования работы с открытым исходным кодом, полностью написанная на Java и предназначенная для использования в обоих J2SE и J2EE Приложений. Он предлагает большую гибкость, не жертвуя простотой.
Можно создавать сложные графики для выполнения любого задания. Примерами могут быть, например, задачи, выполняемые ежедневно, каждую две пятницы в 19:30 .m или только в последний день каждого месяца.
В этой статье мы посмотрим на элементы, чтобы построить работу с кварцевым API. Для введения в сочетании с весной, мы рекомендуем планирование весной с кварцем .
2. Мейвен зависимостей
Мы должны добавить следующую зависимость к пом.xml:
org.quartz-scheduler quartz 2.3.0
Последнюю версию можно найти в Maven Центральный репозиторий .
3. Кварцевый API
Сердцем каркаса является Расписание . Он отвечает за управление средой времени работы нашего приложения.
Для обеспечения масштабируемости кварц основан на многотемной архитектуре. При его начале фреймвасец инициализирует набор рабочих потоков которые используются Расписание для выполнения Вакансии .
Таким образом, фреймворка может работать Вакансии одновременно. Он также опирается на слабо связанный набор ThreadPool компоненты управления для управления средой потока.
Ключевыми интерфейсами API являются:
- Планировщик – основной API для взаимодействия с планировщиком фреймворка
- Работа – интерфейс, который должен быть реализован компонентами, которые мы хотели бы вы выполнили
- JobDetail — для определения экземпляров Работа секунда
- Триггер – компонент, определяющий график, по которому имеется данный Работа будет выполняться
- JobBuilder – используется для создания JobDetail экземпляры, определяющие экземпляры Рабочих мест
- ТриггерСтроитель — используется для создания Триггер Экземпляров
Давайте рассмотрим каждый из этих компонентов.
4. Планировщик
Прежде чем мы сможем использовать Расписание , он должен быть мгновенно. Для этого мы можем использовать заводскую РасписаниеФактория :
SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler();
Расписание жизненный цикл ограничен его созданием, через РасписаниеФактория и призыв к его выключения () метод. Когда-то создал Расписание интерфейс можно использовать для добавления, удаления и Вакансии и Триггеры и выполнять другие операции, связанные с планированием (например, приостановку триггера).
Тем не менее, Расписание не будет действовать на каких-либо триггеров, пока он не был начат с начало () метод :
scheduler.start();
5. Вакансии
Работа это класс, который реализует Работа интерфейс. Он имеет только один простой метод:
public class SimpleJob implements Job { public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println("This is a quartz job!"); } }
Когда Работа вызвать пожары, выполнить () метод вызывается одним из потоков работника планировщика.
JobExecutionКонтекст объект, передаваемый этому методу, предоставляет экземпляр задания с информацией о среде времени выполнения, ручку Расписание , который выполнил его, ручку к Триггер что вызвало выполнение, работа JobDetail объект, и несколько других элементов.
JobDetail объект создается кварцевым клиентом в момент Работа добавляется в планировщик. По существу, это определение экземпляра задания :
JobDetail job = JobBuilder.newJob(SimpleJob.class) .withIdentity("myJob", "group1") .build();
Этот объект может также содержать различные настройки свойств для Работа , а также JobDataMap , которые могут быть использованы для хранения государственной информации для данного экземпляра нашего рабочего класса.
5.1. JobDataMap
JobDataMap используется для хранения любого количества объектов данных, которые мы хотим сделать доступными для экземпляра задания при его выполнении. JobDataMap является реализацией Java- Карта интерфейс и имеет некоторые дополнительные методы удобства для хранения и извлечения данных примитивных типов.
Вот пример вовся данных в JobDataMap при строительстве JobDetail , перед добавлением задания в планировщик:
JobDetail job = newJob(SimpleJob.class) .withIdentity("myJob", "group1") .usingJobData("jobSays", "Hello World!") .usingJobData("myFloatValue", 3.141f) .build();
Вот пример того, как получить доступ к этим данным во время выполнения задания:
public class SimpleJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap dataMap = context.getJobDetail().getJobDataMap(); String jobSays = dataMap.getString("jobSays"); float myFloatValue = dataMap.getFloat("myFloatValue"); System.out.println("Job says: " + jobSays + ", and val is: " + myFloatValue); } }
Выше пример будет печатать “Работа говорит Привет мир!”, И валь 3.141 “.
Мы также можем добавить методы сеттера в наш класс работы, который соответствует именам ключей в JobDataMap.
Если мы сделаем это, по умолчанию Кварц РаботаФактория реализация автоматически вызывает этих сеттеров, когда задание мгновенно, тем самым предотвращая необходимость явно получить значения из карты в рамках нашего метода выполнения.
6. Триггеры
Триггер объекты используются для запуска выполнения Вакансии .
Когда мы хотим запланировать Работа , мы должны мгновенно триггера и настроить его свойства, чтобы настроить наши требования к планированию:
Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("myTrigger", "group1") .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(40) .repeatForever()) .build();
Триггер может также иметь JobDataMap связанных с ним. Это полезно для передачи параметров в Работа которые специфичны для исполнения триггера.
Существуют различные типы триггеров для различных потребностей планирования. Каждый из них имеет разные ТриггерКей свойства для отслеживания их идентификационных данных. Тем не менее, некоторые другие свойства являются общими для всех типов триггеров:
- jobKey свойство указывает личность задания, которое должно быть выполнено при срабатывании триггера.
- startTime свойство указывает, когда график триггера впервые вступает в силу. Значение является java.util.Date объект, определяющий момент времени для данной календарной даты. Для некоторых типов триггеров триггер срабатывает в данный момент времени запуска. Для других, это просто знаменует собой время, что график должен начаться.
- конец времени свойство указывает, когда расписание триггера должно быть отменено.
Кварцевые корабли с горсткой различных типов триггеров, но наиболее часто используемые из них ПростойТриггер и КронТриггер .
6.1. Приоритет
Иногда, когда у нас есть много триггеров, Кварц не может иметь достаточно ресурсов, чтобы немедленно уволить все рабочие места планируется запустить в то же время. В этом случае мы можем захотеть сначала контролировать, какой из наших триггеров будет доступен. Это именно то, что приоритетная свойство на триггере используется для.
Например, , когда десять триггеров заготовятся одновременно и доступны всего четыре потока рабочих, первые четыре триггера с наивысшим приоритетом будут выполнены первыми. Если мы не устанавливаем приоритет на триггере, он использует приоритет по умолчанию из пяти. Любое интегративное значение допускается в качестве приоритета, положительного или отрицательного.
В приведенной ниже примере у нас есть два триггера с разным приоритетом. Если ресурсов недостаточно для одновременного запуска всех триггеров, триггерА будет первым, кто будет уволен:
Trigger triggerA = TriggerBuilder.newTrigger() .withIdentity("triggerA", "group1") .startNow() .withPriority(15) .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(40) .repeatForever()) .build(); Trigger triggerB = TriggerBuilder.newTrigger() .withIdentity("triggerB", "group1") .startNow() .withPriority(10) .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(20) .repeatForever()) .build();
6.2. Инструкции по осечке
Осечка возникает, если постоянный триггер Скучает по его время стрельбы из-за планировщик выключаются или в случае, если в пуле потоков Кварца нет доступных потоков.
Различные типы триггеров имеют различные инструкции по осечке. По умолчанию они используют интеллектуальную инструкцию по политике. Когда планировщик запускается, он ищет любые стойкие триггеры, которые осечки. После этого он обновляет каждый из них на основе их индивидуально настроенных инструкций осечек.
Рассмотрим примеры, приведенные ниже:
Trigger misFiredTriggerA = TriggerBuilder.newTrigger() .startAt(DateUtils.addSeconds(new Date(), -10)) .build(); Trigger misFiredTriggerB = TriggerBuilder.newTrigger() .startAt(DateUtils.addSeconds(new Date(), -10)) .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withMisfireHandlingInstructionFireNow()) .build();
Мы запланировали запуск триггера 10 секунд назад (так что это 10 секунд поздно к тому времени, когда он создан), чтобы имитировать осечку, например, потому, что планировщик был вниз или не было достаточного количества рабочих потоков доступны. Конечно, в реальном мире сценарий, мы бы никогда не график триггеров, как это.
В первом триггере ( misFiredTriggerA ) инструкции по обработке осечек не устанавливаются. Отсюда и называется интеллектуальные политические используется в этом случае и называется: сMisfireHandlingInstructionFireNow(). Это означает, что задание выполняется сразу после того, как планировщик обнаруживает осечку.
Второй триггер четко определяет, какое поведение мы ожидаем при осечке. В этом примере, это просто происходит, чтобы быть той же умной политики.
6.3. Простойтриггер
ПростойТриггер используется для сценариев, в которых мы должны выполнить задание в определенный момент времени. Это может быть точно один раз или неоднократно через определенные промежутки времени.
Примером может быть пожар при исполнении задания ровно в 12:20:00 13 января 2018 года. Точно так же мы можем начинать в это время, а затем еще пять раз, каждые десять секунд.
В приведеном ниже коде дата myStartTime ранее был определен и используется для создания триггера для одной конкретной времени :
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity("trigger1", "group1") .startAt(myStartTime) .forJob("job1", "group1") .build();
Далее, давайте построим триггер для определенного момента времени, а затем повторять каждые десять секунд десять раз:
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity("trigger2", "group1") .startAt(myStartTime) .withSchedule(simpleSchedule() .withIntervalInSeconds(10) .withRepeatCount(10)) .forJob("job1") .build();
6.4. КронТриггер
КронТриггер используется, когда нам нужны расписания, основанные на календарных заявлениях. Например, мы можем указать графики стрельбы, такие как каждую пятницу в полдень или каждый будний день в 9:30 .
Cron-Expressions используются для настройки экземпляров КронТриггер . Эти выражения состоят из Струны которые состоит из семи суб-выражений. Мы можем прочитать больше о Крон-выражения здесь .
В приведенном ниже примере мы создаем триггер, который стреляет каждую минуту с 8 утра до 5 вечера, каждый день:
CronTrigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger3", "group1") .withSchedule(CronScheduleBuilder.cronSchedule("0 0/2 8-17 * * ?")) .forJob("myJob", "group1") .build();
7. Заключение
В этой статье мы показали, как построить Расписание вызвать Работа . Мы также видели некоторые из наиболее распространенных вариантов триггера, используемых: ПростойТриггер и КронТриггер .
Кварц может быть использован для создания простых или сложных графиков для выполнения десятков, сотен или даже больше рабочих мест. Более подробную информацию о рамках можно найти на основных веб- .
Исходный код примеров можно найти более на GitHub .