tareas quartz programadas example annotation java spring synchronization quartz-scheduler

programadas - spring quartz scheduler in java example



Asegúrese de que la ejecución del trabajo de Spring Quartz no se superponga (7)

Tengo un programa Java que se ejecuta desde Spring Qquartz cada 20 segundos. A veces solo lleva unos segundos ejecutar, pero a medida que los datos crecen, estoy seguro de que se ejecutan durante 20 segundos o más.

¿Cómo puedo evitar que Quartz active / active el trabajo mientras se está ejecutando una instancia? Disparar 2 trabajos realizando las mismas operaciones en una base de datos no sería tan bueno. ¿Hay alguna forma de que pueda hacer algún tipo de sincronización?


Cuarzo 1

Si cambia su clase para implementar StatefulJob en lugar de Job, Quartz se encargará de esto por usted. De StatefulJob javadoc :

Los trabajos con estado no pueden ejecutarse al mismo tiempo, lo que significa que los nuevos activadores que se producen antes de que se complete la ejecución del método de ejecución (xx) se retrasarán.

StatefulJob extiende Job y no agrega ningún método nuevo, por lo que todo lo que necesita hacer para obtener el comportamiento que desea es cambiar esto:

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

A esto:

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

Cuarzo 2

En la versión 2.0 de Quartz, StatefulJob está en desuso. Ahora se recomienda utilizar anotaciones, por ejemplo,

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


En caso de que alguien haga referencia a esta pregunta, StatefulJob ha quedado en desuso. Ahora sugieren que use anotaciones en su lugar ...

@PersistJobDataAfterExecution @DisallowConcurrentExecution public class TestJob implements Job {

Esto explicará lo que significan esas anotaciones ...

Las anotaciones provocan el comportamiento tal como lo describen sus nombres: no se permitirán varias instancias del trabajo para que se ejecuten simultáneamente (considere un caso en el que un trabajo tenga código en su método execute () que demore 34 segundos en ejecutarse, pero está programado con un disparador que se repite cada 30 segundos), y tendrá su contenido JobDataMap re-persistido en el JobStore del planificador después de cada ejecución. Para los fines de este ejemplo, solo la anotación @PersistJobDataAfterExecution es realmente relevante, pero siempre es aconsejable usar la anotación @DisallowConcurrentExecution con ella, para evitar condiciones de carrera en los datos guardados.


No estoy seguro de que desee la sincronización, ya que la segunda tarea se bloqueará hasta que termine la primera, y terminará con una acumulación. Puede colocar los trabajos en una cola, pero según su descripción, parece que la cola puede crecer indefinidamente.

Investigaría ReadWriteLock s, y dejaría que su tarea establezca un bloqueo mientras se está ejecutando. Las tareas futuras pueden inspeccionar este bloqueo y salir inmediatamente si todavía se está ejecutando una tarea anterior. Por experiencia, he descubierto que esa es la manera más confiable de abordar esto.

Tal vez también genere una advertencia para que sepa que tiene problemas y aumente el intervalo de tiempo en consecuencia.


Puedes usar un semáforo. Cuando se toma el semáforo, abandone el segundo trabajo y espere hasta la próxima vez que lo haga.


ponerlos en una cola

Incluso si el tiempo excede 20 segundos, el trabajo actual debe estar terminado y luego el siguiente debe ser obtenido de la cola.

O también puede aumentar el tiempo hasta una cantidad razonable.


si usas el cuarzo de primavera, creo que tienes que configurar de esta manera

<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>


Si todo lo que necesitas hacer es disparar cada 20 segundos, Quartz es una exageración seria. El java.util.concurrent.ScheduledExecutorService debe ser perfectamente suficiente para ese trabajo.

El ScheduledExecutorService también proporciona dos semánticas para la programación. "tasa fija" intentará ejecutar su trabajo cada 20 segundos independientemente de la superposición, mientras que la "demora fija" intentará dejar 20 segundos entre el final del primer trabajo y el inicio del siguiente. Si desea evitar la superposición, entonces el retraso fijo es más seguro.