确保 Spring Quartz 作业执行不重叠
我有一个 Java 程序,每 20 秒从 Spring Qquartz 执行一次。有时只需要几秒钟即可执行,但随着数据变大,我确信它会运行 20 秒或更长时间。
当一个实例仍在执行时,如何防止 Quartz 触发/触发作业?解雇两个在数据库上执行相同操作的作业不太好。有什么方法可以进行某种同步吗?
I have a Java program that executes from Spring Qquartz every 20 seconds. Sometimes it takes just few seconds to execute, but as data gets bigger I'm sure it run for 20 seconds or more.
How can I prevent Quartz from firing/triggering the job while one instance is still being executed? Firing 2 jobs performing same operations on a database would not be so good. Is there a way I can do some kind of synchronization?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
Quartz 1
如果您更改类以实现 StatefulJob 而不是 Job,Quartz 将为您处理这个问题。来自 StatefulJob javadoc:
StatefulJob 扩展了 Job 并且不添加任何新方法,因此要获得所需的行为,您所需要做的就是更改以下内容:
改为:
Quartz 2
在 Quartz 2.0 版本中,不推荐使用
StatefulJob
。现在建议使用注释来代替,例如Quartz 1
If you change your class to implement StatefulJob instead of Job, Quartz will take care of this for you. From the StatefulJob javadoc:
StatefulJob extends Job and does not add any new methods, so all you need to do to get the behaviour you want is change this:
To this:
Quartz 2
In version 2.0 of Quartz,
StatefulJob
is deprecated. It is now recommended to use annotations instead, e.g.如果您需要做的只是每 20 秒触发一次,那么 Quartz 就显得严重矫枉过正了。
java.util.concurrent.ScheduledExecutorService
应该完全足以完成这项工作。ScheduledExecutorService
还提供两种调度语义。 "固定速率" 将尝试每 20 秒运行一次作业,无论重叠情况如何,而 “固定延迟” 将尝试在第一个作业结束和下一个作业开始之间留出 20 秒。如果你想避免重叠,那么固定延迟是最安全的。If all you need to do is fire every 20 seconds, Quartz is serious overkill. The
java.util.concurrent.ScheduledExecutorService
should be perfectly sufficient for that job.The
ScheduledExecutorService
also provides two semantics for scheduling. "fixed rate" will attempt to run your job every 20 seconds regardless of overlap, whereas "fixed delay" will attempt to leave 20 seconds between the end of the first job and the start of the next. If you want to avoid overlap, then fixed-delay is safest.以防万一有人提到这个问题,StatefulJob 已被弃用。他们现在建议您使用注释......
这将解释这些注释的含义......
Just in case anyone references this question, StatefulJob has been deprecated. They now suggest you use annotations instead...
This will explain what those annotations mean...
如果你使用弹簧石英,我想你必须这样配置
if you use spring quartz, i think you have to configure like this
我不确定您是否想要同步,因为第二个任务将阻塞,直到第一个任务完成,并且您最终会积压。您可以将作业放入队列中,但从您的描述来看,队列可能会无限期地增长。
我会调查 ReadWriteLock s,并让您的任务在运行时设置锁定。未来的任务可以检查此锁,如果旧任务仍在运行,则立即退出。我从经验中发现这是解决这个问题最可靠的方法。
也许还会生成警告,以便您知道遇到问题并相应地增加时间间隔?
I'm not sure you want synchronisation, since the second task will block until the first finishes, and you'll end up with a backlog. You could put the jobs in a queue, but from your description it sounds like the queue may grow indefinitely.
I would investigate ReadWriteLocks, and let your task set a lock whilst it is running. Future tasks can inspect this lock, and exit immediately if an old task is still running. I've found from experience that that's the most reliable way to approach this.
Perhaps generate a warning as well so you know you're encountering problems and increase the time interval accordingly ?
您可以使用信号量。当信号量被拿走时,放弃第二项工作,等待下一次触发时间。
You can use a semaphore. When the semaphore is taken, abandon the 2nd job and wait until the next fire time.
将它们放入队列
即使时间超过 20 秒,当前作业也应该完成 &那么应该从队列中获取下一个。
或者您也可以将时间增加到合理的范围。
put them in a queue
Even if the time exceeds 20 second current job should be finished & then the next should be fetched from the queue.
Or you can also increase time to some reasonable amount.