scheduleAtFixedRate vs scheduleWithFixedDelay
Asked Answered
T

8

156

What's the main difference between scheduleAtFixedRate and scheduleWithFixedDelay methods of ScheduledExecutorService?

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.

Togo answered 9/7, 2014 at 9:22 Comment(0)
E
259

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.

Eurhythmy answered 9/7, 2014 at 9:26 Comment(5)
What happens in the fixedRate scenario if it takes more than an hour to make coffee?Emboss
@BrettVanderVeen: I believe that depends on the executor in question. It will be scheduled on time - but whether that executes depends on whether or not a thread is available to that executor. I suggest you experiment to see how this works in various scenarios.Eurhythmy
@BrettVanderVeen From the documentation, "If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute." In other words, a conforming implementation would not allow the next one to execute until the previous one finishes.Hodges
Can you provide a working code for the output shown (coffee) for a novice like me?Breechblock
@MuneshSingh: Not in this question, which is asking to explain what the difference is between scheduling at a fixed rate and scheduling at a fixed delay. You wouldn't implement this yourself anyway though - you'd use the built-in executors.Eurhythmy
P
77

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

time series of invocation scheduleAtFixedRate method

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

time series of invocation scheduleWithFixedDelay method

Hope can help you

Parabolize answered 8/9, 2014 at 3:29 Comment(4)
I could not understand the "extra" word mentioned in scheduleAtFixedRate time series diagram.Breechblock
@Breechblock It is meant to show that the execution time of the task is longer than scheduled, so it takes "extra" time and the next execution starts right away.Bevins
@Bevins thanks for clarifying. Does that mean "period" is not exactly a fixed time delay between two consecutive executions.Breechblock
@Breechblock The period is fixed, but it won't stop the current task once it passes it, there would simply be no delay between this run and the next. If you want to create a "timeout" you might want to retain the Future and the cancel it in a different executor. In simple words, it says start first execution and the next one as soon as possible after "period" time passes.Bevins
R
22

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

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

Rajkot answered 10/9, 2018 at 15:46 Comment(1)
You wrote twice scheduleAtFixedRate :)Crosby
L
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.

Lib answered 9/7, 2014 at 9:26 Comment(0)
V
3

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 .

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

Vocalism answered 9/7, 2014 at 10:5 Comment(4)
What? JVM will decide? What is that even supposed to mean? It is true that the runnable will not get executed concurrently with itself as per docs, but it's decided by the executor, which may be custom OR the standard ScheduledThreadPoolExecutor (and the latter has well defined behaviour)Compile
No i have found similar issue in my application where i have given 15 min interval and first task is not getting finished in 15 min and take 15.30 sec so second task didn't get immediately started it some thime start after 5 min and some time after 8 min and i am not aware that whether we can control this behavior as this is not standard behavior .Vocalism
That sounds like textbook task queuing.Compile
Yes, it just means that all threads in your executor are already busy doing something, and your task gets put in a queue of things to do. (NOTE you need to confirm this by either looking at said queue or looking at what the executor threads are doing). How you control this depends on what type of executor you have. You may want to make a separate 1-thread executor for this particular task only, then it won't wait on anything. Or give your current executor more threads. Or change it's strategy.Compile
O
1

I can see your premiss but your conclusion is not quite right. Here is a good and quite complete explanation according to this Tutorial for understanding the diferences bitween these two.

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

This method schedules a task to be executed periodically. The task is executed the first time after the initialDelay, and then recurringly every time the period expires. If any execution of the given task throws an exception, the task is no longer executed. If no exceptions are thrown, the task will continue to be executed until the ScheduledExecutorService is shut down. If a task takes longer to execute than the period between its scheduled executions, the next execution will start after the current execution finishes. The scheduled task will not be executed by more than one thread at a time.

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

This method works very much like scheduleAtFixedRate() except that the period is interpreted differently. In the scheduleAtFixedRate() method the period is interpreted as a delay between the start of the previous execution, until the start of the next execution. In this method, however, the period is interpreted as the delay between the end of the previous execution, until the start of the next. The delay is thus between finished executions, not between the beginning of executions.

Oakman answered 28/10, 2021 at 7:1 Comment(0)
C
0

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

scheduleWithFixedDelay keeps delay
scheduleAtFixedRate removes delay

Crosby answered 30/11, 2019 at 12:4 Comment(0)
H
-2
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

Helianthus answered 13/8, 2019 at 13:15 Comment(1)
Please also explain how the code solves the OP's problem. :)Defant

© 2022 - 2024 — McMap. All rights reserved.