Подтвердить что ты не робот

Убедитесь, что выполнение задания Spring Quartz не перекрывается

У меня есть Java-программа, которая выполняется от Spring Qquartz каждые 20 секунд. Иногда выполнение занимает всего несколько секунд, но по мере увеличения данных я уверен, что он работает в течение 20 секунд или более.

Как я могу предотвратить Quartz от запуска/запуска задания, пока один экземпляр все еще выполняется? Увольнение 2 заданий, выполняющих те же операции в базе данных, было бы не очень хорошим. Есть ли способ сделать какую-то синхронизацию?

4b9b3361

Ответ 1

Если все, что вам нужно сделать, это огонь каждые 20 секунд, Кварц серьезно переборщит. java.util.concurrent.ScheduledExecutorService должен быть вполне достаточным для этой работы.

ScheduledExecutorService также предоставляет две семантики для планирования. "fixed rate" будет пытаться выполнять вашу работу каждые 20 секунд независимо от перекрытия, тогда как "Фиксированная задержка" будет пытаться оставить 20 секунд между окончанием первого задания и началом следующего. Если вы хотите избежать перекрытия, то фиксированная задержка является наиболее безопасной.

Ответ 2

Кварц 1

Если вы измените свой класс для реализации StatefulJob вместо Job, Quartz позаботится об этом для вас. Из StatefulJob javadoc:

задания с сохранением работоспособности не разрешены выполнять одновременно, что означает триггеры, которые происходят до завершение метода execute (xx) будет отложено.

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

public class YourJob implements org.quartz.Job {
    void execute(JobExecutionContext context) {/*implementation omitted*/}
}

Для этого:

public class YourJob implements org.quartz.StatefulJob {
    void execute(JobExecutionContext context) {/*implementation omitted*/}
}

Кварц 2

В версии 2.0 кварца StatefulJob устарел. Вместо этого теперь рекомендуется использовать аннотации, например.

@DisallowConcurrentExecution
public class YourJob implements org.quartz.Job {
    void execute(JobExecutionContext context) {/*implementation omitted*/}
}

Ответ 3

На всякий случай кто-либо ссылается на этот вопрос, StatefulJob устарел. Теперь они предлагают использовать аннотации вместо этого...

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class TestJob implements Job {

Это объяснит, что означают эти аннотации...

Аннотации приводят к поведению так же, как и их имена описывают - несколько экземпляры задания не будут разрешено работать одновременно (учтите случай, когда работа имеет код в своем execute(), который занимает 34 секунды для запуска, но это запланировано с помощью триггер, повторяющийся каждые 30 секунд) и будет иметь JobDataMap содержание повторяется в планировщик JobStore после каждого выполнение. Для целей этого пример, только @PersistJobDataAfterExecution аннотация действительно актуальна, но всегда разумно использовать @DisallowConcurrentExecution аннотации с ним, чтобы предотвратить условия гонки на сохраненные данные.

Ответ 4

если вы используете кварц spring, я думаю, вам нужно настроить как это

    <bean id="batchConsumerJob"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="myScheduler" />
        <property name="targetMethod" value="execute" />
        <property name="concurrent" value="false" />
    </bean>

Ответ 5

Я не уверен, что вы хотите синхронизировать, так как вторая задача будет блокироваться до тех пор, пока первая не закончится, и у вас закончится отставание. Вы можете помещать задания в очередь, но из вашего описания это звучит так, что очередь может расти бесконечно.

Я бы исследовал ReadWriteLock s, и пусть ваша задача устанавливает блокировку во время ее работы. Будущие задачи могут проверить этот замок и немедленно выйти, если старая задача все еще запущена. Я нашел по опыту, что это самый надежный способ приблизиться к этому.

Возможно, генерирует предупреждение, так что вы знаете, что сталкиваетесь с проблемами и соответственно увеличиваете временной интервал?

Ответ 6

поместите их в очередь

Даже если время превышает 20 секунд, текущее задание должно быть закончено, а затем следующее из очереди должно быть извлечено из очереди.

Или вы также можете увеличить время до некоторой разумной суммы.

Ответ 7

Вы можете использовать семафор. Когда семафор взят, откройте второе задание и дождитесь следующего пожара.