Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A Future<V> is a typed handle for the eventual result of an asynchronous computation. In Java, methods such as ExecutorService.submit() return a Future so you can retrieve the result later, wait with a timeout, check completion, or request cancellation. Its main retrieval method, get(), blocks until the task finishes unless you use its timed form.

What is a Java Future?

Oracle defines a Future as representing the result of an asynchronous computation. The handle separates submitting work from observing its outcome: the task can run on an executor while the calling thread does other work.

For example, submit(Callable<T>) returns a Future<T>. A Callable can return a value and throw checked exceptions:

ExecutorService pool = Executors.newFixedThreadPool(2);
Future<Integer> future = pool.submit(() -> {
    Thread.sleep(200);
    return 42;
});

try {
    int answer = future.get();
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
} catch (ExecutionException e) {
    Throwable cause = e.getCause();
}
pool.shutdown();

The code waits at get() for the submitted computation’s outcome. In production code, also account for cancellation and ensure the executor is shut down according to the application’s lifecycle.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What submit returns

  • submit(Callable<T>) returns a Future<T> whose successful result is the Callable’s return value.
  • submit(Runnable) returns a Future<?>; after successful completion, get() normally returns null.
  • submit(Runnable, result) returns the supplied result after the Runnable completes.

What do Future’s methods tell you?

Method Meaning Important detail
get() Waits for completion and returns the result. May block indefinitely; can throw interruption, task-failure, or cancellation exceptions.
get(long timeout, TimeUnit unit) Waits up to the specified duration. Throws TimeoutException if the task is not complete. A timeout alone does not cancel it.
isDone() Reports whether the Future has completed. Completion includes success, exceptional completion, and cancellation; it does not guarantee success.
isCancelled() Reports whether the Future was cancelled before normal completion. A cancelled Future is also done.
cancel(boolean mayInterruptIfRunning) Requests cancellation. The argument controls whether interruption of a running worker is attempted; it does not forcibly stop arbitrary code.

Does Future.get() block, and how do timeouts work?

get() waits as long as needed for the computation to finish. If the caller must not wait indefinitely, use get(timeout, unit). When that wait expires, the caller receives TimeoutException; the task may still be running in the executor.

If the application wants work to stop after a timeout, it must separately request cancellation, typically with cancel(true), and the task must respond to interruption. A timeout limits the wait, not the computation.

How should you handle Future failures and interruption?

The timed and untimed forms of get() can report different outcomes. Handle them according to whether the caller should stop waiting, report a task failure, or propagate cancellation.

  • InterruptedException means the thread waiting in get() was interrupted. After any needed cleanup, a common handler restores the interrupt status with Thread.currentThread().interrupt(), as in the example.
  • ExecutionException means the task failed. Inspect getCause() to find the underlying exception or error thrown by the computation.
  • CancellationException means the Future was cancelled.
  • TimeoutException is thrown by timed get() when the wait ends before completion; it does not itself signal that the task stopped.

Does cancel(true) stop the task?

No. Cancellation is cooperative: the Future API says cancellation need not abruptly terminate its computation. If cancellation succeeds before the task starts, execution is suppressed. If it is already running, mayInterruptIfRunning determines whether the implementation attempts to interrupt the worker thread.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

An interrupt is a request, not a forceful kill. A task must cooperate—for example, by using interruptible operations or checking and responding to interruption during CPU-bound work. Blocking I/O and third-party calls also need suitable interruption or cancellation behavior; otherwise a task may continue despite the cancellation request.

What happens when a Future completes?

The Java SE API specifies a memory-visibility guarantee: actions taken by the asynchronous computation happen-before actions following the corresponding Future.get() in another thread. Consequently, after a successful get(), the caller can observe the task’s actions performed before it completed. Oracle Java SE 26 Future API

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Future versus CompletableFuture

Use a plain Future when a component submits work and later needs one result, a blocking wait, a timeout, or cancellation. Use CompletableFuture when the work is part of a composed asynchronous flow: it implements Future and adds completion-stage operations so later work can be chained or combined without calling get() at every stage.

Consideration Future CompletableFuture
Retrieval Typically retrieve through blocking get() or timed get(). Can retrieve through Future methods and also continue through completion stages.
Composition A handle for one task outcome; no built-in stage chaining. Supports chaining and combination, including thenApply, thenCompose, and allOf.
Error handling get() reports task failure as ExecutionException. Completion-stage error paths include operations such as exceptionally.
Cancellation Cancellation may request interruption, but is cooperative. Implements Future’s cancellation contract; composition does not make arbitrary running code forcibly stoppable.

Choose based on the shape of the work: one result that the caller can wait for suits Future; a pipeline, fan-in, or asynchronous continuation suits CompletableFuture.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Which JDK versions support Future’s newer methods?

The classic Future methods such as get(), cancel(), and isDone() date to Java 5. Java SE 19 introduced the default methods resultNow(), exceptionNow(), and state(), which are also documented in the Java SE 26 API. These methods provide non-blocking access when the caller already knows the Future has completed; they throw IllegalStateException when the requested state or result is unavailable. Check the minimum JDK version required by your application or library before using them. Oracle Java SE 26 Future API

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.