139

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);

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

4

8 回答 8

234

Try adding a Thread.sleep(1000); call within your run() method... Basically it's the difference between scheduling something based on when the previous execution ends and when it (logically) starts.

For example, suppose I schedule an alarm to go off with a fixed rate of once an hour, and every time it goes off, I have a cup of coffee, which takes 10 minutes. Suppose that starts at midnight, I'd have:

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

If I schedule with a fixed delay of one hour, I'd have:

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

Which one you want depends on your task.

于 2014-07-09T09:26:26.183 回答
69

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

调用 scheduleAtFixedRate 方法的时间序列

scheduleWithFixedDelay调用方法的时间序列。下一个执行将在一个执行终止和下一个执行开始之间的延迟时间之后开始,无论其执行时间如何

调用 scheduleWithFixedDelay 方法的时间序列

希望能帮到你

于 2014-09-08T03:29:58.277 回答
11

scheduleAtFixedRate()方法创建一个新任务,并在每个周期将其提交给执行器,无论之前的任务是否完成

另一方面,该方法在前一个任务完成后scheduleWithFixedDelay()创建一个新任务。

于 2018-09-10T15:46:40.873 回答
5

If you read the Java Doc it will be clearer

ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.

ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given delay between the termination of one execution and the commencement of the next.

于 2014-07-09T09:26:46.017 回答
2

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

我认为这将帮助您选择方法,因为因此我遇到了大问题

于 2014-07-09T10:05:42.753 回答
0

我可以看到你的前提,但你的结论并不完全正确。这是根据本教程的一个很好且非常完整的解释,用于理解这两者之间的差异。

scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)

此方法调度要定期执行的任务。该任务在 initialDelay 之后第一次执行,然后每次周期到期时重复执行。如果给定任务的任何执行引发异常,则不再执行该任务。如果没有抛出异常,任务将继续执行,直到 ScheduledExecutorService 关闭。如果一个任务的执行时间比其计划执行之间的时间长,则下一次执行将在当前执行完成后开始。计划任务一次不会被多个线程执行。

scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)

此方法的工作原理与 scheduleAtFixedRate() 非常相似,只是对周期的解释不同。在 scheduleAtFixedRate() 方法中,周期被解释为上一次执行开始到下一次执行开始之间的延迟。但是,在此方法中,周期被解释为上一次执行结束到下一次执行开始之间的延迟。因此,延迟是在完成的执行之间,而不是在执行开始之间。

于 2021-10-28T07:01:09.467 回答
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消除延迟

于 2019-11-30T12:04:26.747 回答
-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);

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

于 2019-08-13T13:15:38.693 回答