scheduleAtFixedRate vs scheduleWithFixedDelay

时间:2014-07-09 09:22:14

标签: java scheduled-tasks scheduledexecutorservice

ScheduledExecutorServicescheduleAtFixedRatescheduleWithFixedDelay方法之间的主要区别是什么?

scheduler.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println("scheduleAtFixedRate:    " + new Date());
    }
}, 1, 3L , SECONDS);

scheduler.scheduleWithFixedDelay(new Runnable() {
    @Override
    public void run() {
        System.out.println("scheduleWithFixedDelay: " + new Date());
    }
}, 1, 3L , SECONDS);

它们在同一时间打印完全相同,似乎它们以完全相同的间隔执行。

7 个答案:

答案 0 :(得分:158)

尝试在Thread.sleep(1000);方法中添加run()来电...基本上,根据前一次执行结束的时间安排某些内容与之间的区别它(逻辑上)开始

例如,假设我按照每小时一次的固定费率安排闹钟,每次关闭时,我都会喝一杯咖啡,需要10分钟。假设从午夜开始,我有:

00:00: Start making coffee
00:10: Finish making coffee
01:00: Start making coffee
01:10: Finish making coffee
02:00: Start making coffee
02:10: Finish making coffee

如果我安排一个小时的固定延迟,我会:

00:00: Start making coffee
00:10: Finish making coffee
01:10: Start making coffee
01:20: Finish making coffee
02:20: Start making coffee
02:30: Finish making coffee

你想要哪一个取决于你的任务。

答案 1 :(得分:47)

可视化调用scheduleAtFixedRate方法的时间序列。如果最后一次执行时间超过句点,则立即开始下一次执行。否则,它将在一段时间后开始。

time series of invocation scheduleAtFixedRate method

调用scheduleWithFixedDelay方法的时间序列。下一次执行将在一次执行终止和下一次执行开始之间的延迟时间之后开始,而不管其执行时间

time series of invocation scheduleWithFixedDelay method

希望可以帮到你

答案 2 :(得分:2)

scheduleAtFixedRate()方法创建一个新任务,并在每个时段将其提交给执行者,无论先前任务是否完成

另一方面,scheduleAtFixedDelay()方法在上一个任务完成后创建一个新任务

答案 3 :(得分:1)

如果您阅读Java Doc,那将更加清晰

ScheduledFuture scheduleAtFixedRate(Runnable命令,long initialDelay,long period,TimeUnit unit) 创建并执行一个周期性操作,该操作在给定的初始延迟后首先启用,随后在给定的时间段内启用;执行将在initialDelay之后开始,然后是initialDelay + period,然后是initialDelay + 2 * period,依此类推。

ScheduledFuture scheduleWithFixedDelay(Runnable命令,long initialDelay,long delay,TimeUnit unit) 创建并执行一个定期动作,该动作在给定的初始延迟之后首先被启用,并且随后在一次执行的终止和下一次执行的开始之间给定延迟。

答案 4 :(得分:1)

如果第一个线程花费的时间过长并且没有在给定的持续时间内结束,那么scheduleAtFixedRate中有一个catch,那么第一个任务将被完成后第二个conscutive线程将无法启动,并且在第一个线程完成任务时不会立即启动和gievn持续时间已经过去。 JVM将决定下一个任务何时执行。

我认为这会帮助你选择Becuase方法,因为我遇到了大问题

答案 5 :(得分:0)

让我们编写一个简单的程序:

import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

var time = 0L
var start = System.currentTimeMillis()
val executor = Executors.newScheduledThreadPool(1)
executor.scheduleWithFixedDelay({
    if (time >= 12_000L) {
        executor.shutdown()
    } else {
        Thread.sleep(2000L)
        val now = System.currentTimeMillis()
        time += now - start
        System.out.println("Total $time delay ${now - start}\n")
        start = now
    }
}, 0L, 1000L, TimeUnit.MILLISECONDS)

并查看结果:

| scheduleWithFixedDelay |   scheduleAtFixedRate  |
|:----------------------:|:----------------------:|
| Total 2001 delay 2001  | Total 2003 delay 2003  |
| Total 5002 delay 3001  | Total 4004 delay 2001  |
| Total 8003 delay 3001  | Total 6004 delay 2000  |
| Total 11003 delay 3000 | Total 8004 delay 2000  |
| Total 14003 delay 3000 | Total 10005 delay 2001 |
|          ---           | Total 12005 delay 2000 |

注意执行时间大于等待时间

scheduleWithFixedDelay 保持延迟
scheduleAtFixedRate 消除延迟

答案 6 :(得分:-1)

scheduledExecutorService.scheduleAtFixedRate(() -> {
        System.out.println("runnable start"); try { Thread.sleep(5000);  System.out.println("runnable end");} catch
     (InterruptedException e) { // TODO Auto-generated catch block
      e.printStackTrace(); }}, 2, 7, TimeUnit.SECONDS);



     scheduledExecutorService.scheduleWithFixedDelay(() -> {
     System.out.println("runnable start"); try { Thread.sleep(5000); System.out.println("runnable end");} catch
     (InterruptedException e) { // TODO Auto-generated catch block
     e.printStackTrace(); } }, 2, 7, TimeUnit.SECONDS);

只需执行它,您就会知道其中的区别。谢谢