确保Spring Quartz作业执行不重叠

ant*_*ant 46 java spring synchronization quartz-scheduler

我有一个Java程序,每20秒从Spring Qquartz执行一次.有时执行只需几秒钟,但随着数据变大,我确信它会运行20秒或更长时间.

当一个实例仍在执行时,如何防止Quartz触发/触发作业?在数据库上执行2个执行相同操作的作业并不是那么好.有没有办法可以做某种同步?

Dón*_*nal 134

石英1

如果你改变你的类来实现StatefulJob而不是Job,Quartz会为你处理这个问题.来自StatefulJob javadoc:

不允许有状态作业同时执行,这意味着在执行(xx)方法完成之前发生的新触发器将被延迟.

StatefulJob扩展了Job并且没有添加任何新方法,所以你需要做的就是改变它:

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

对此:

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

石英2

在Quartz 2.0版中,StatefulJob不推荐使用.现在建议使用注释,例如

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

  • 这是这个问题的正确答案.谢谢. (20认同)
  • 使用此解决方案,尝试的作业实例排队,对吧?你怎么阻止他们排队? (4认同)
  • 正确答案是这样的.为什么OP已经接受了另一个提出替代方式的答案? (3认同)
  • @Donal DisallowConcurrentExecution 注释如何维护多个服务器实例之间的非并发性,或者它不是? (2认同)

ska*_*man 31

如果您需要做的就是每20秒发射一次,那么Quartz就会严重过度杀伤.本java.util.concurrent.ScheduledExecutorService应是完成此项工作完全足够.

ScheduledExecutorService还提供了两个语义用于调度."固定费率"将尝试每20秒运行一次,无论重叠如何,而"固定延迟"将尝试在第一个作业结束和下一个作业开始之间留出20秒.如果你想避免重叠,那么固定延迟是最安全的.

  • 如果不在群集中则为真 (9认同)

gsh*_*ger 19

如果有人引用此问题,则StatefulJob已被弃用.他们现在建议你使用注释代替......

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class TestJob implements Job {
Run Code Online (Sandbox Code Playgroud)

这将解释那些注释意味着什么......

注释会引起行为,就像它们的名称所描述的那样 - 不允许多个作业实例同时运行(考虑一个作业在其execute()方法中有代码运行需要34秒才能运行的情况,但是它被调度为触发器每30秒重复一次),并在每次执行后将JobDataMap内容重新保存在调度程序的JobStore中.出于此示例的目的,只有@PersistJobDataAfterExecution批注才真正相关,但使用@DisallowConcurrentExecution批注始终是明智的,以防止保存数据的竞争条件.