How to set a Timer in Java?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Java offers more than one way to schedule code for later execution. The older java.util.Timer API still works for simple cases, but for most modern applications ScheduledExecutorService is the better choice because it is more flexible, better behaved with exceptions, and fits the rest of the concurrency APIs.
The Old-School Option: java.util.Timer
Timer runs scheduled tasks on a background thread. It is easy to use for simple one-off or repeating jobs:
This schedules the task once after a two-second delay.
For repeated execution:
That starts after one second and then repeats every three seconds.
Why ScheduledExecutorService Is Usually Better
The modern alternative is ScheduledExecutorService from java.util.concurrent. It integrates more naturally with thread pools and is usually the better default for production code.
Here is a one-time scheduled task:
And here is a repeating task:
This gives you predictable scheduling with a clean shutdown path.
Fixed Rate vs Fixed Delay
Java exposes two repeating patterns with ScheduledExecutorService:
- '
scheduleAtFixedRatetries to maintain a regular schedule' - '
scheduleWithFixedDelaywaits a fixed delay after one execution finishes before starting the next'
Example of fixed delay:
Use fixed rate when the schedule itself matters, such as polling every minute. Use fixed delay when each run may take variable time and you want breathing room between runs.
Cancelling a Timer Task
You often need the ability to stop the scheduled work. With ScheduledExecutorService, keep the returned handle:
This is one of the reasons the executor-based API is more practical than the older Timer class.
When Timer Is Still Acceptable
Timer is fine for small programs, throwaway tools, or examples where only one simple background schedule exists. Once you care about multiple tasks, resilience, or integration with other concurrency features, the executor API is usually worth it.
Common Pitfalls
A common mistake is forgetting to shut down the scheduler. Background threads can keep the application alive longer than expected.
Another pitfall is using Timer for tasks that may block or throw exceptions. Because Timer is relatively simple and often single-threaded, one bad task can interfere with the rest of the schedule.
Developers also confuse fixed rate and fixed delay. They sound similar, but they produce different timing behavior under load.
Finally, scheduled tasks should stay small and quick where possible. A timer is not a substitute for a full job system.
Summary
- Java can schedule tasks with either
TimerorScheduledExecutorService. - '
ScheduledExecutorServiceis usually the better modern default.' - Use
schedule()for one-time work and fixed-rate or fixed-delay methods for repetition. - Keep a handle if you need to cancel a repeating task.
- Shut schedulers down cleanly and choose the timing mode that matches your workload.

