How can I implement a Runnable with timeout?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
In Java, timeout behavior is usually implemented around a Runnable, not inside the Runnable interface itself. The standard pattern is to submit the task to an ExecutorService, wait through a Future, and cancel the task if it runs past the deadline.
Wrap the Runnable in an Executor Task
A Runnable has no built-in timeout API, so you need an execution framework that can track completion. ExecutorService provides that by returning a Future from submit.
This is the usual production answer because it keeps the task logic separate from the timeout policy. The Runnable does the work. The caller decides how long it is allowed to run.
Understand What Cancellation Actually Means
future.cancel(true) does not forcibly kill code at an arbitrary instruction. It sends an interruption request to the worker thread. The task must cooperate by either reacting to InterruptedException or checking the interrupted flag.
That cooperative model is important. If the task ignores interruption or blocks in an API that does not respond to interruption, the timeout may expire while the underlying work continues.
Use Callable When a Result Matters
If the caller needs a return value, switch to Callable instead of trying to mutate shared state from a Runnable. The timeout logic stays the same.
This is often a cleaner design because it avoids extra shared variables and makes completion semantics explicit.
Consider a Scheduled Cancellation for Reuse
If many parts of the application need the same timeout behavior, a helper method can hide the boilerplate. One common variation is to submit the work and schedule a cancellation request separately.
The same rule still applies: cancellation is only effective if the task cooperates.
Common Pitfalls
- Assuming a timeout can force-stop arbitrary Java code immediately.
- Ignoring interruption inside the task and then wondering why cancellation appears ineffective.
- Using raw
Threadmanagement instead of the higher-level executor APIs. - Choosing
Runnablewhen the caller really needs a computed result and should useCallable. - Forgetting to shut down the executor, which can leave non-daemon threads alive after the work is done.
Summary
- Implement timeouts with
ExecutorServiceandFuture, not by extendingRunnable. - Use
future.get(timeout, unit)to wait for completion up to a deadline. - Call
future.cancel(true)on timeout and make the task cooperate with interruption. - Prefer
Callablewhen the task should return a value. - Treat timeout handling as cooperative cancellation, not forced termination.
Related reading
- How can I implement asynchronous functions when writing to a Serial COM Port?
- How can I implement client-side async calls with WCF's ChannelFactoryT?
- How can I improve async data retrieval and caching?
- How can I keep my fork in sync without adding a separate remote?
- How can I implement static methods on an interface?
- How can I increment a date by one day in Java?
- How can I limit Parallel.ForEach?
- How can I limit Parallel.ForEach?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.