ScheduledExecutorService in Java
ScheduledExecutorService is an executor that can run a task after a delay or repeatedly at a regular interval. It is used for jobs such as sending reminders, refreshing a cache every minute, or retrying a failed request after a pause. It replaces the older Timer class (see "Timer and TimerTask in Java"): it uses a pool of threads, keeps running when one task fails, and accepts lambdas. In this lesson, you will learn its three scheduling methods.
Methods
| Method | Description |
|---|---|
schedule(task, delay, unit) | It is used to run a task once after a delay; returns a ScheduledFuture. |
scheduleAtFixedRate(task, initialDelay, period, unit) | It starts runs at fixed intervals measured from the start of each run. |
scheduleWithFixedDelay(task, initialDelay, delay, unit) | It waits a fixed delay after the end of each run before the next. |
ScheduledFuture.cancel(mayInterrupt) | It cancels a scheduled or repeating task. |
Fixed Rate vs Fixed Delay
Example: A One-Time Reminder and a Repeating Task
Let's see an example that schedules a reminder and a repeating heartbeat, then stops the heartbeat after three beats.
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Scheduler {
public static void main(String[] args) throws Exception {
try (ScheduledExecutorService ses =
Executors.newScheduledThreadPool(2)) {
ScheduledFuture<String> reminder = ses.schedule(
() -> "Reminder for Navika: submit the project",
350, TimeUnit.MILLISECONDS);
AtomicInteger beats = new AtomicInteger();
CountDownLatch threeBeats = new CountDownLatch(3);
ScheduledFuture<?> heartbeat = ses.scheduleAtFixedRate(() -> {
System.out.println("heartbeat " + beats.incrementAndGet());
threeBeats.countDown();
}, 0, 200, TimeUnit.MILLISECONDS);
threeBeats.await();
heartbeat.cancel(false);
System.out.println(reminder.get());
System.out.println("Heartbeat canceled? "
+ heartbeat.isCancelled());
}
}
}heartbeat 1
heartbeat 2
heartbeat 3
Reminder for Navika: submit the project
Heartbeat canceled? trueExplanation: The heartbeat starts at once and repeats every 200 milliseconds (at 0, 200 and 400). The reminder is scheduled for 350 milliseconds; its text is ready before the third beat, but the main thread prints it only after waiting for three beats with a CountDownLatch. heartbeat.cancel(false) stops the repeating task, and reminder.get() returns the result of the one-time task. Closing the executor in try-with-resources shuts it down.
ScheduledExecutorService vs Timer
Timer | ScheduledExecutorService | |
|---|---|---|
| Threads | One | A pool |
| A task throws an exception | The timer dies; later tasks never run | Only that task's repetitions stop |
| Tasks | Must extend TimerTask | Any Runnable or Callable (lambdas) |
| Results | None | ScheduledFuture with get() |
Common Mistakes
Letting an exception escape a repeating task. The schedule stops without any message.
Using fixed rate for tasks that may run longer than the period. Runs then bunch up; use fixed delay.
Forgetting to shut the scheduler down. Its threads keep the program alive.
Practice
- Easy: Schedule a message "Time for a break, Srihitha" after two seconds, and shut the scheduler down after it runs.
- Harder: Write a retry helper that calls a task, and if it throws, schedules another attempt after 100, 200 and then 400 milliseconds.
Key Takeaways
Was this tutorial helpful?