Java 预定春季的固定费率和固定延迟有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38842507/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
what different between fixed rate and fixed delay in schedule spring?
提问by Adam
I am implementing scheduled tasks using spring and i see have 2 type config time that scheduled works again from latest. What different between 2 type this config.
我正在使用 spring 实施计划任务,并且我看到有 2 种类型的配置时间,这些时间从最新开始再次起作用。2 键入此配置有什么不同。
@Scheduled(fixedDelay = 5000)
public void doJobDelay() {
// do anything
}
@Scheduled(fixedRate = 5000)
public void doJobRate() {
// do anything
}
回答by kuhajeyan
- fixedRate : makes Spring run the task on periodic intervals even if the last invocation may still be running.
- fixedDelay : specifically controls the next execution time when the last execution finishes.
- fixedRate :使 Spring 定期运行任务,即使最后一次调用可能仍在运行。
- fixedDelay :具体控制上次执行完成后的下一次执行时间。
In code:
在代码中:
@Scheduled(fixedDelay=5000)
public void updateEmployeeInventory(){
System.out.println("employee inventory will be updated once only the last updated finished ");
/**
* add your scheduled job logic here
*/
}
@Scheduled(fixedRate=5000)
public void updateEmployeeInventory(){
System.out.println("employee inventory will be updated every 5 seconds from prior updated has stared, regardless it is finished or not");
/**
* add your scheduled job logic here
*/
}
回答by Jinen Kothari
Fixed Delay: specifically controls the next execution time when the last execution finishes.
Fixed Delay:具体控制上次执行完成后的下一次执行时间。
Fixed Rate: makes Spring run the task on periodic intervals even if the last invocation may be still running.
固定速率:即使最后一次调用可能仍在运行,Spring 也会定期运行任务。
回答by nikhil7610
"fixedRate" : waits for X millis from the start of previous execution before starting next execution. If current execution exceeds 'fixedRate' interval, the next execution is queued and this will create a series of tasks running ie multiple instances of tasks will be running.
"fixedRate" : 从上一次执行开始等待 X 毫秒,然后再开始下一次执行。如果当前执行超过“fixedRate”间隔,则下一次执行将排队,这将创建一系列正在运行的任务,即将运行多个任务实例。
private static int i = 0;
@Scheduled(initialDelay=1000, fixedRate=1000)
public void testScheduling() throws InterruptedException {
System.out.println("Started : "+ ++i);
Thread.sleep(4000);
System.out.println("Finished : "+ i);
}
Output:
输出:
Started : 1
Finished : 1 // after 4 seconds
Started : 2 // immediately w/o waiting for 1 sec as specified in fixed rate
Finished : 2 // after 4 seconds
and so on
Started : 1
Finished : 1 // 4 秒后
Started : 2 // 立即不按固定速率指定等待 1 秒
Finished : 2 // 4 秒后
,依此类推
"fixedDelay" : waits for X millis from the end of previous execution before starting next execution. Doesn't matter how much time current execution is taking, the next execution is started after adding 'fixedDelay' interval to end time of current execution. It will not queue next execution.
"fixedDelay" : 在开始下一次执行之前等待 X 毫秒从上一次执行结束。无论当前执行花费了多少时间,在将“fixedDelay”间隔添加到当前执行的结束时间后开始下一次执行。它不会排队下次执行。
private static int i = 0;
@Scheduled(initialDelay=1000, fixedDelay=1000)
public void testScheduling() throws InterruptedException {
System.out.println("Started : "+ ++i);
Thread.sleep(4000);
System.out.println("Finished : "+ i);
}
Output:
输出:
Started : 1
Finished : 1 // after 4 seconds Started : 2 // waits for 1 second as specified in fixedDelay Finished : 2 // after 4 seconds Started : 3 // after 1 second
and so on
Started : 1
Finished : 1 // 4 秒后 Started : 2 // 等待固定延迟中指定的 1 秒 Finished : 2 // 4 秒后 Started : 3 // 1 秒后
,依此类推
回答by ahmetcetin
fixedRate:This is used to run the scheduled jobs in every n milliseconds. It does not matter whether the job has already finished its previous turn or not.
fixedRate:用于每 n 毫秒运行一次计划作业。作业是否已经完成上一回合无关紧要。
fixedDelay:It is used to run the scheduled job sequentially with the given n milliseconds delay time between turns. Which means, the time spent on the job will affect the start time of the next run of scheduled job.
fixedDelay:用于以给定的 n 毫秒延迟时间顺序运行计划作业。这意味着,在作业上花费的时间会影响下一次计划作业运行的开始时间。
fixedRate Example:
固定利率示例:
@Scheduled(fixedRate = 5000)
public void runJobWithFixedRate() {
...
}
Let's assume the job is triggered at 13:00:00 for the first time:
假设作业第一次在 13:00:00 触发:
- 1st run-> 13:00:00, job finishes at 13:00:02
- 2nd run-> 13:00:05, job finishes at 13:00:08
- 3rd run-> 13:00:10, job finishes at 13:00:16
- 4th run-> 13:00:15, job finishes at 13:00:18
- 第一次运行-> 13:00:00,作业在 13:00:02 完成
- 第二次运行-> 13:00:05,作业在 13:00:08 完成
- 第三次运行-> 13:00:10,作业在 13:00:16 完成
- 第 4 次运行-> 13:00:15,作业在 13:00:18 完成
fixedDelay Example:
固定延迟示例:
@Scheduled(fixedDelay = 5000)
public void runJobWithFixedDelay() {
...
}
Let's assume the job is triggered at 13:00:00 for the first time:
假设作业第一次在 13:00:00 触发:
- 1st run-> 13:00:00, job finishes at 13:00:02
- 2nd run-> 13:00:07, job finishes at 13:00:08
- 3rd run-> 13:00:13, job finishes at 13:00:16
- 4th run-> 13:00:21, job finishes at 13:00:25
- 第一次运行-> 13:00:00,作业在 13:00:02 完成
- 第二次运行-> 13:00:07,作业在 13:00:08 完成
- 第三次运行-> 13:00:13,作业在 13:00:16 完成
- 第 4 次运行-> 13:00:21,作业在 13:00:25 完成
When to use "fixedRate": fixedRate is appropriate if it is not expected to exceed the size of the memory and the thread pool. If the incoming tasks do not finish quick, it may end up with "Out of Memory exception"
何时使用“fixedRate”:如果预计不会超过内存和线程池的大小,则fixedRate 是合适的。如果传入的任务没有快速完成,它可能会以“内存不足异常”告终
When to use "fixedDelay":If every running task is relevant to each other and they need to wait before the previous one finishes, fixedDelay is suitable. If fixedDelay time is set carefully, it will also let the running threads enough time to finish their jobs before the new task starts
何时使用“fixedDelay”:如果每个正在运行的任务彼此相关并且需要等待前一个任务完成,则fixedDelay是合适的。如果fixedDelay时间设置得仔细,它也会让正在运行的线程有足够的时间在新任务开始之前完成他们的工作
回答by fifman
One thing which should be clarified is that fixedRate
does not mean executions will start with a certain time interval.
应该澄清的一件事是,fixedRate
这并不意味着执行将以一定的时间间隔开始。
If one execution cost too much time (more than the fixed rate), the next execution will only start AFTERthe previous one finishes, unless @Async
and @EnableAsync
are provided. The following source codes which are part of Spring's ThreadPoolTaskScheduler
implementation explain why:
如果一个执行成本太多时间(比固定利率多),接下来的执行才会开始后的前一个结束,除非@Async
和@EnableAsync
提供。作为 SpringThreadPoolTaskScheduler
实现的一部分的以下源代码解释了原因:
@Override
public void run() {
Date actualExecutionTime = new Date();
super.run();
Date completionTime = new Date();
synchronized (this.triggerContextMonitor) {
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
if (!this.currentFuture.isCancelled()) {
schedule();
}
}
}
You can see that only after the previous task is finished (super.run()
), the next task is scheduled (schedule()
). With @Async
and @EnableAsync
, super.run()
is an async function which will return immediately, thus the next task does not have to wait for the previous one to actually finish.
可以看到,只有在上一个任务完成后(super.run()
),才会安排下一个任务(schedule()
)。随着@Async
和@EnableAsync
,super.run()
是一个异步函数,它会立即返回,因此,接下来的任务不必等待前一时间的实际完成。
回答by Ammar Akouri
We can run a scheduled task using Spring's @Scheduled
annotation but based on the properties fixedDelay
and fixedRate
the nature of execution changes.
我们可以使用 Spring 的@Scheduled
注解运行计划任务,但基于属性fixedDelay
和fixedRate
执行更改的性质。
The
fixedDelay
property makes sure that there is a delay ofn
millisecond
between thefinish time
of an execution of a task and thestart time
of the next execution of the task.
该
fixedDelay
属性确保在任务的执行和任务的下一次执行n
millisecond
之间存在延迟。finish time
start time
This property is specifically useful when we need to make sure that only one instance of the task runs all the time. For dependent jobs, it is quite helpful.
当我们需要确保只有一个任务实例始终运行时,此属性特别有用。对于依赖的工作,这是非常有帮助的。
The
fixedRate
property runs the scheduled task at everyn
millisecond
. It doesn't check for any previous executions of the task.
该
fixedRate
属性在每个n
millisecond
. 它不检查任务的任何先前执行。
This is useful when all executions of the task are independent. If we don't expect to exceed the size of the memory and the thread pool, fixedRate
should be quite handy.
当任务的所有执行都是独立的时,这很有用。如果我们不期望超过内存和线程池的大小,fixedRate
应该相当得心应手。
But, if the incoming tasks do not finish quickly, it's possible they end up with “Out of Memory exception”.
但是,如果传入的任务没有快速完成,它们最终可能会出现“内存不足异常”。
回答by Johannes Rudolph
There seems to be conflicting advice on what these methods do. Maybe the behavior can change depending on the taskScheduler
or Executor
bean registered with the spring context. I found @Ammar Akouri's answer to be the most close.
关于这些方法的作用似乎存在相互矛盾的建议。也许行为会根据在spring 上下文中注册的taskScheduler
或Executor
bean 而改变。我发现@Ammar Akouri 的答案是最接近的。
Here's what I found when using a ScheduledThreadPoolExecutor
(full test source provided below)
这是我在使用ScheduledThreadPoolExecutor
(下面提供的完整测试源)时发现的
- neither
fixedDelay
norfixedRate
allow concurrent task executions fixedDelay
will wait for the endof a previous invocation, then schedule a new inovcation at a fixed amount of time in the future. It will hence not queue up more than one task at a time.fixedRate
will schedule a new invocation every period. It will queue up more than one task at a time (potentially unbounded) but will never execute tasks concurrently.
- 既不允许
fixedDelay
也fixedRate
不允许并发任务执行 fixedDelay
将等待前一次调用的结束,然后在未来的固定时间安排新的调用。因此,它一次不会排队多个任务。fixedRate
将在每个时期安排一次新的调用。它将一次排队多个任务(可能是无限的),但永远不会并发执行任务。
Sample Test (Kotlin/JUnit):
示例测试(Kotlin/JUnit):
class LearningSchedulerTest {
private lateinit var pool: ScheduledExecutorService
@Before
fun before() {
pool = Executors.newScheduledThreadPool(2)
}
@After
fun after() {
pool.shutdown()
}
/**
* See: https://stackoverflow.com/questions/24033208/how-to-prevent-overlapping-schedules-in-spring
*
* The documentation claims: If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
* https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html#scheduleAtFixedRate-java.lang.Runnable-long-long-java.util.concurrent.TimeUnit-
*/
@Test
fun `scheduleAtFixedRate schedules at fixed rate`() {
val task = TaskFixture( initialSleep = 0)
pool.scheduleAtFixedRate({task.run()}, 0, 10, TimeUnit.MILLISECONDS )
Thread.sleep(15)
Assert.assertEquals(2, task.invocations.get())
Thread.sleep(10)
Assert.assertEquals(3, task.invocations.get())
Thread.sleep(10)
// 1 initial and 3 periodic invocations
Assert.assertEquals(4, task.invocations.get())
}
@Test
fun `scheduleAtFixedRate catches up on late invocations`() {
val task = TaskFixture(initialSleep = 30)
pool.scheduleAtFixedRate({task.run()}, 0, 10, TimeUnit.MILLISECONDS )
Thread.sleep(15) // we see no concurrent invocations
Assert.assertEquals(1, task.invocations.get())
Thread.sleep(10) // still no concurrent invocations
Assert.assertEquals(1, task.invocations.get())
Thread.sleep(10)
// 1 initial and 3 periodic invocations
Assert.assertEquals(4, task.invocations.get())
}
@Test
fun `scheduleWithFixedDelay schedules periodically`() {
val task = TaskFixture( initialSleep = 0)
pool.scheduleWithFixedDelay({task.run()}, 0, 10, TimeUnit.MILLISECONDS )
Thread.sleep(35)
// 1 initial and 3 periodic invocations
Assert.assertEquals(4, task.invocations.get())
}
@Test
fun `scheduleWithFixedDelay does not catch up on late invocations`() {
val task = TaskFixture( initialSleep = 30)
pool.scheduleWithFixedDelay({task.run()}, 0, 10, TimeUnit.MILLISECONDS )
Thread.sleep(35)
// 1 initial invocation, no time to wait the specified 10ms for a second invocation
Assert.assertEquals(1, task.invocations.get())
}
class TaskFixture(val initialSleep: Long) {
var invocations = AtomicInteger()
fun run() {
invocations.incrementAndGet()
if (invocations.get() == 1){
Thread.sleep(initialSleep)
}
}
}
}
回答by bashar
The fixedDelay property makes sure that there is a delay of n millisecond between the finish time of an execution of a task and the start time of the next execution of the task.
fixedDelay 属性确保任务执行的完成时间和任务下一次执行的开始时间之间存在 n 毫秒的延迟。
This property is specifically useful when we need to make sure that only one instance of the task runs all the time. For dependent jobs, it is quite helpful.
当我们需要确保只有一个任务实例始终运行时,此属性特别有用。对于依赖的工作,这是非常有帮助的。
The fixedRate property runs the scheduled task at every n millisecond. It doesn't check for any previous executions of the task.
fixedRate 属性每 n 毫秒运行一次计划任务。它不检查任务的任何先前执行。
This is useful when all executions of the task are independent. If we don't expect to exceed the size of the memory and the thread pool, fixedRate should be quite handy.
当任务的所有执行都是独立的时,这很有用。如果我们不期望超过内存和线程池的大小,fixedRate 应该非常方便。
But, if the incoming tasks do not finish quickly, it's possible they end up with “Out of Memory exception”.
但是,如果传入的任务没有快速完成,它们最终可能会出现“内存不足异常”。
For more details visit: https://www.baeldung.com/spring-scheduled-tasks