Future and CompletableFuture in Java

 

Future and CompletableFuture in Java

Introduction

Java provides multiple ways to perform asynchronous programming, and one of the key features introduced for this is the Future and CompletableFuture API. These classes help in executing long-running tasks in the background and improve performance by utilizing multi-threading.



In this article, we will explore Future and CompletableFuture in Java, their differences, advantages, and how they help in writing more efficient and non-blocking code.

What is Future in Java?

Future<T> is an interface introduced in Java 5 as part of the java.util.concurrent package. It represents the result of an asynchronous computation and provides methods to check if the computation is complete, retrieve the result, or cancel the computation.

Key Methods in Future Interface

  • get(): Retrieves the result, blocking if necessary.

  • get(long timeout, TimeUnit unit): Retrieves the result but waits only for a specified time.

  • isDone(): Checks if the task is completed.

  • isCancelled(): Checks if the task was canceled.

  • cancel(boolean mayInterruptIfRunning): Cancels the task if possible.

Example of Future in Java

import java.util.concurrent.*;

public class FutureExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Integer> future = executor.submit(() -> {
            Thread.sleep(2000);
            return 10;
        });

        System.out.println("Doing something else while waiting...");
        System.out.println("Result: " + future.get()); // Blocks until result is available
        executor.shutdown();
    }
}

Limitations of Future

  1. Blocking Behavior: Calling get() blocks execution until the result is available.

  2. No Manual Completion: There is no way to manually complete a Future.

  3. No Chaining: Lacks support for chaining multiple asynchronous computations.

What is CompletableFuture?

Java 8 introduced CompletableFuture<T> in java.util.concurrent, which extends Future and overcomes its limitations. It provides powerful features for asynchronous programming, including chaining, combining multiple futures, and handling exceptions.

Key Features of CompletableFuture

  • Non-blocking Execution: Supports callbacks (thenApply, thenAccept, thenRun).

  • Combining Multiple Tasks: Methods like thenCombine and allOf allow multiple futures to work together.

  • Exception Handling: exceptionally and handle help manage errors.

  • Manual Completion: complete() allows manually completing a future.

Example of CompletableFuture

import java.util.concurrent.*;

public class CompletableFutureExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            try { Thread.sleep(2000); } catch (InterruptedException e) {}
            return 10;
        });
        
        future.thenApply(result -> result * 2)
              .thenAccept(result -> System.out.println("Result: " + result));
        
        Thread.sleep(3000); // Waiting for async execution
    }
}

Chaining Futures

CompletableFuture.supplyAsync(() -> "Hello")
    .thenApply(result -> result + " World")
    .thenAccept(System.out::println);

Combining Multiple Futures

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);

CompletableFuture<Integer> result = future1.thenCombine(future2, Integer::sum);
System.out.println("Sum: " + result.get());

Handling Exceptions

CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Error!"); })
    .exceptionally(ex -> {
        System.out.println("Exception: " + ex.getMessage());
        return 0;
    })
    .thenAccept(System.out::println);

Difference Between Future and CompletableFuture

Feature Future CompletableFuture
Blocking Yes, get() blocks No, supports non-blocking callbacks
Chaining No Yes, supports thenApply, thenCompose
Exception Handling No built-in support Has exceptionally, handle
Manual Completion No Yes, with complete()
Combining Futures No Yes, with thenCombine, allOf

Conclusion

Future and CompletableFuture are essential for asynchronous programming in Java. While Future is useful, CompletableFuture provides more flexibility, better exception handling, and non-blocking execution. For modern Java applications, CompletableFuture is the recommended choice.

Previous
Next Post »