1. Планирование задач на одной машине, задачи могут перекрываться и выполняться одновременно.
Например: выполнять эту задачу каждые 10 секунд, но выполнение задачи занимает 20 секунд.
Результаты выполнения (перекрывающееся выполнение задач):
решать:Можно добавить к одной машинеИспользование DisallowConcurrentExecutionрешать,Кластерная среда должна опираться на распределенную, например.quartzКластерное решение,Если перекрытие выполнения задач не может быть гарантировано,доступныйРаспределенная блокировкаили выполнение задачиИдемпотентностьгарантировать。
Пример:Используйте аннотацииDisallowConcurrentExecutionрешать效果:
Результат выполнения:
2、использоватьИспользование DisallowConcurrentExecution来решать任务重叠问题,Возможно, из-за задачиДлительное время выполнения приводит к неточному планированию задач.。
Пример:
Результаты выполнения (цикл планирования задач связан с затратами времени и больше не является точным — выполнение каждые 10 секунд, время занимает 20 секунд):
Если выполняемые задачи выполняются с перекрытием, то (период планирования задач должен преобладать – выполнение каждые 10 секунд):
Причина явлений 1 и 2 заключается в том, что при получении задач, которые можно планировать (память по умолчанию хранит задания задач и информацию о планировании):
org.quartz.simpl.RAMJobStore#acquireNextTriggers
заслуженныйПри получении триггера задачи информация о его хранилище также будет удалена.:
существоватьПрежде чем задача будет фактически запланирована,В зависимости от того, возможно ли перекрывающееся выполнение,еслиЕсли перекрывающееся выполнение возможно, триггер будет добавлен и сохранен снова, и следующий опрос планирования задач можно будет запланировать снова.:
org.quartz.simpl.RAMJobStore#triggersFired
когдаКогда задача выполнена,Задачи, которые не могут быть выполнены с перекрытием, также будут сохранены повторно.,в следующий раз Планирование опрос задачи можно запланировать повторно:
org.quartz.simpl.RAMJobStore#triggeredJobComplete
3、Задача будет обусловленаВ пуле потоков задач нет бездействующих потоков для выполнения, что приводит к ожиданию потока планирования, и задача больше не будет запланирована.。
Задачи, полученные потоком планирования задач, будут переданы в пул рабочих потоков для планирования. По умолчанию используется пул потоков фиксированного размера SimpleThreadPool. Если в пуле потоков нет простаивающих потоков для выполнения задачи, поток планирования будет продолжать ждать. :
org.quartz.core.QuartzSchedulerThread#run
org.quartz.simpl.SimpleThreadPool#blockForAvailableThreads
выполнить:
4. Если задачу необходимо остановить и продолжить планирование, вы можете создать исключение JobExecutionException и установить информацию:
Преобразование в CompletedExecutionInstruction на основе информации об исключении:
Определите, можно ли продолжать планировать задачу на основе CompletedExecutionInstruction:
org.quartz.simpl.RAMJobStore#triggeredJobComplete
Прикрепил:
package com.renzhikeji.demo;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.concurrent.TimeUnit;
public class QuartzDemo {
public static void main(String[] args) throws SchedulerException, InterruptedException {
//Создаем планировщик
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//Создаем триггер
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
.build();
//Определяем задание
JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("MyJob", "MyJob_Group")
.usingJobData("author", "Техническая команда когнитивных технологий").build();
//Используем jobDateMap
job.getJobDataMap().put("Официальный аккаунт WeChat", "Техническая команда когнитивных технологий");
//запускать
scheduler.start();
//Запланировать это задание
scheduler.scheduleJob(job, trigger);
TimeUnit.HOURS.sleep(1);
scheduler.shutdown(true);
}
public static class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) {
System.out.println("hello begin " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("hello end " + Thread.currentThread().getName());
}
}
}
1. Руководство по предотвращению ошибок Java: предотвращение ошибок ScheduledThreadPoolExecutor