Java scheduleAtFixedRate 与 scheduleWithFixedDelay

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24649842/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 13:44:52  来源:igfitidea点击:

scheduleAtFixedRate vs scheduleWithFixedDelay

javascheduled-tasksscheduledexecutorservice

提问by Sawyer

What's the main difference between scheduleAtFixedRateand scheduleWithFixedDelaymethods of 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);

they print exact the same time, seems they are executed at exact the same interval.

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

采纳答案by Jon Skeet

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 endsand when it (logically) starts.

尝试Thread.sleep(1000);在您的run()方法中添加一个调用...基本上,这是根据前一次执行结束时间和(逻辑上)开始时间安排某事之间的区别。

For example, suppose I schedule an alarm to go off with a fixed rateof 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:

例如,假设我安排闹钟以每小时一次的固定频率响起,每次响起时,我都会喝杯咖啡,这需要 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

If I schedule with a fixed delayof 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.

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

回答by shazin

If you read the Java Doc it will be clearer

如果您阅读 Java Doc 会更清楚

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 scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)创建并执行一个周期性动作,在给定的初始延迟后首先启用,然后在给定的时间段内启用;即执行将在 initialDelay 之后开始,然后是 initialDelay+period,然后是 initialDelay + 2 * period,依此类推。

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.

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

回答by user1047873

There is one catch in scheduleAtFixedRate if first thread is taking too long and not ended in given duration then second conscutive thread will not start once the first task will get finsished and will not imediately get started while the first thread has comepleted their task and gievn duration has been elapsed. JVM Will decide when the next task will get executed .

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

I think that will help you to choose method Becuase due to this i got big problem

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

回答by Ken Block

Visualize time series of invocation scheduleAtFixedRatemethod. Next executions will start immediately if the last one takes longer than period. Otherwise, it will start after period time.

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

time series of invocation scheduleAtFixedRate method

调用 scheduleAtFixedRate 方法的时间序列

Time series of invocation scheduleWithFixedDelaymethod. Next execution will start after delay time between termination of one execution and the commencement of the next, regardless of its execution time

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

time series of invocation scheduleWithFixedDelay method

调用 scheduleWithFixedDelay 方法的时间序列

Hope can help you

希望能帮到你

回答by Imar

The scheduleAtFixedRate()method creates a new task and submits it to the executor every period, regardless of whether or not the previous task finished.

scheduleAtFixedRate()方法会创建一个新任务,并在每个周期将其提交给执行程序,而不管上一个任务是否完成

On the other hand, the scheduleWithFixedDelay()method creates a new task after the previous task has finished.

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

回答by logi tech

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

Just execute it, and you will know the difference. Thank you

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

回答by Vlad

Let's write a simple program:

我们来写一个简单的程序:

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)

And see the results:

并查看结果:

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

NOTICE the execution time is bigger than waiting

注意执行时间大于等待

scheduleWithFixedDelaykeeps delay
scheduleAtFixedRateremoves delay

scheduleWithFixedDelay保持延迟
scheduleAtFixedRate删除延迟