usar quartz example ejemplos ejemplo como java scheduling scheduled-tasks quartz-scheduler

example - quartz scheduler java ejemplos



Quartz Java retomando un trabajo lo ejecuta muchas veces (3)

Para mi aplicación creo trabajos y los programo con CronTriggers. Cada trabajo tiene un solo desencadenador y tanto el nombre del trabajo como los nombres del desencadenador son iguales. Ningún trabajo comparte un disparador.

Ahora cuando creo un disparador de cron como este "0/1 * * * *?" que le indica al trabajo que ejecute cada segundo, funciona bien.

El problema surge cuando hago una primera pausa en el trabajo llamando a:

scheduler.pauseJob(jobName, jobGroup);

y luego reanudar el trabajo después de decir 50 segundos con:

scheduler.resumeJob(jobName, jobGroup);

Lo que veo es que durante estos 50 segundos el trabajo no se ejecutó como se solicitó. ¡Pero en el momento en que reanudo el trabajo veo 50 ejecuciones del trabajo al mismo tiempo!

Pensé que esto se debía a la configuración predeterminada para la instrucción de fallo de encendido, pero incluso después de configurar la instrucción de fallo de encendido del activador al crearlo:

trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);

Lo mismo sucede. ¿Alguien puede sugerir una manera de arreglar esto?


Al menos desde la versión 1.6.5 (la primera versión de cuarzo a mi alcance), el programador tiene un método pauseTrigger que toma el nombre / grupo como parámetros. Esto significa que no tiene que tener una subclase de cada tipo de activador que usa, ni tampoco tiene que hacer trucos funky de eliminación / inserción.

Ambos son importantes para mí porque 1) nuestra base de datos tiene una política estricta de no eliminar y 2) el almacén de datos personalizado que uso no admite subclases de activación.


El CronTrigger funciona recordando nextFireTime . Después de crear el disparador se inicializa nextFireTime . Cada vez que se activa el nextFireTime se actualiza nextFireTime . Dado que el trabajo no se activa cuando está pausado, nextFireTime permanece "antiguo". Por lo tanto, después de reanudar el trabajo, el activador devolverá cada tiempo de activación anterior.

El problema es que el disparador no sabe que está en pausa. Para superar esto hay un mal manejo. Después de reanudar los trabajos, se updateAfterMisfire() método updateAfterMisfire() del updateAfterMisfire() que corrige nextFireTime . Pero no si la diferencia entre nextFireTime y ahora es menor que el misfireThreshold . Entonces el método nunca se llama. El valor predeterminado de este umbral es 60,000. Por lo tanto, si su período de pausa fuera más largo de 60 años, todo estaría bien.

Como tienes problemas, asumo que no lo es. ;) Para solucionar esto, puede modificar el umbral o usar un envoltorio simple alrededor de CronTrigger :

public class PauseAwareCronTrigger extends CronTrigger { // constructors you need go here @Override public Date getNextFireTime() { Date nextFireTime = super.getNextFireTime(); if (nextFireTime.getTime() < System.currentTimeMillis()) { // next fire time after now nextFireTime = super.getFireTimeAfter(null); super.setNextFireTime(nextFireTime); } return nextFireTime; } }


Si detiene el trabajo, el disparador continuará disparándose, pero las ejecuciones se pondrán en cola hasta que se reanude el trabajo. Esto no es un disparador de encendido incorrecto, por lo que la configuración no tendrá ningún efecto.

Lo que quieres hacer, creo, es desactivar o eliminar mediante programación el activador cron, en lugar de pausar el trabajo. Cuando quieras reanudar, vuelve a agregar el disparador.