Мы внедрили кварц для составления расписания. У каждой работы были разные ключи. До сих пор она работала нормально.Вчера мы столкнулись с проблемой, поскольку одно и то же задание выполняется дважды или трижды (без особого поведения) двумя разными потоками Quartz-Worker.Мы не можем сделать пул потоков размером один, так как нам нужны параллельные задания.
Одна заметная вещь в нашем запланированном задании состоит в том, что он перепланирует (ежедневно, еженедельно или ежемесячно) сам при каждом запуске, т.е. если задание запланировано на ежедневноезатем он перенесет себя в следующие 24 часа, но со случайным заранее (скажем, 3 часа) временным окном.Например, если задание выполнялось сегодня в 4:10 (то есть между 4:00 и 7:00), тогда наша работа перенесет себя на завтра в произвольное время между 4:00 и 7:00.Это может быть 4:01 или 6:59 или 5:23 или любое другое значение в данном временном окне.Этот процесс также работал нормально, и он все еще работает нормально в большинстве случаев, за исключением некоторых случаев, когда наш алгоритм перепланирования не может планировать себя в течение следующих 24 часов.Вместо этого он сам планирует в течение следующих 10 секунд, 1 часа или любого другого случайного значения.Но он, наконец, стабилизируется после 2-3 таких неправильных перепланировок, то есть, наконец, запланирует себя на следующие 24 часа.Мы подозреваем, что это может происходить из-за того, что несколько потоков обращаются к объекту Calendar (мы используем Calendar.getInstance () и cal.add (Calendar.DAY_OF_YEAR, 1), чтобы перепланировать работу на следующие 24 часа).Каким-то образом экземпляр календаря выбирает неправильное время или не может добавить один день в текущее время.
Итак, есть две проблемы: 1. Несколько потоков кварца, получающих одно и то же задание 2. Календарь не может добавить заданноеИнтервал или выбирает неправильное текущее время в некоторых конкретных случаях (многопоточный доступ)
Любая помощь будет оценена. Ответ как можно скорее.Спасибо.
Спасибо за ответ.Я хотел бы знать, в чем разница между Statefuljob и аннотацией @DisallowConcurrentExecution и установкой threadPool.threadCount равным 1.
Код для перепланирования имеет вид ...
Calendar cal = Calendar.getInstance();
Calendar nextCal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone(obj.getTimeZone()));
nextCal.setTimeZone(TimeZone.getTimeZone(obj.getTimeZone()));
Date startTime = null;
SimpleTrigger trigger = null;
JobDataMap dataMap = new JobDataMap();
if (repeatTimeInMillis == null) {
cal.set(Calendar.HOUR_OF_DAY, obj.getStartTime());
nextCal.set(Calendar.HOUR_OF_DAY, obj.getStartTime());
cal.set(Calendar.MINUTE, 0);
nextCal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
nextCal.set(Calendar.SECOND, 0);
if (obj.getScheduleType() == ScheduleType.MONTHLY) { // Monthly
log.info("in monthly schedule");
nextCal.add(Calendar.MONTH, 2);
nextCal.set(Calendar.DAY_OF_MONTH, obj.getDate());
cal.add(Calendar.MONTH, 1);
cal.set(Calendar.DAY_OF_MONTH, obj.getDate());
} else if (obj.getScheduleType() == ScheduleType.WEEKLY) { // Weekly
log.info("in weekly schedule");
nextCal.add(Calendar.WEEK_OF_YEAR, 2);
nextCal.set(Calendar.DAY_OF_WEEK, obj.getDay());
cal.add(Calendar.WEEK_OF_YEAR, 1);
cal.set(Calendar.DAY_OF_WEEK, obj.getDay());
} else if (obj.getScheduleType() == ScheduleType.DAILY) { // Daily
log.info("in daily schedule");
nextCal.add(Calendar.DAY_OF_YEAR, 2);
cal.add(Calendar.DAY_OF_YEAR, 1);
}
long time = obj.getTimeWindow() * 60 * 60 * 1000;
time = Math.round(time * Math.random());
cal.setTimeInMillis(cal.getTimeInMillis() + time);
startTime = cal.getTime();
nextCal.setTimeInMillis(nextCal.getTimeInMillis() + time);
repeatTimeInMillis = nextCal.getTimeInMillis() - cal.getTimeInMillis();
log.info("Rescheduling job at " + startTime);
trigger = newTrigger().usingJobData(dataMap)
.withIdentity(obj.getScheduleJobName(), obj.getScheduleJobGroup()).startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInMilliseconds(repeatTimeInMillis).repeatForever())
.build();
} else {
log.info("Rescheduling job next " + repeatTimeInMillis + " milliseconds.");
cal.setTimeInMillis(cal.getTimeInMillis() + repeatTimeInMillis);
startTime = cal.getTime();
trigger = newTrigger().usingJobData(dataMap)
.withIdentity(obj.getScheduleJobName(), obj.getScheduleJobGroup()).startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInMilliseconds(repeatTimeInMillis).withRepeatCount(1)).build();
}