Sobes.tech
Middle

Tell us about the concept of the CompletableFuture class.

sobes.tech AI

Answer from AI

CompletableFuture is a class in Java 8+ that implements the Future and CompletionStage interfaces. It represents an asynchronous computation that can be completed (or fail) at some point in the future, and on which subsequent actions can be performed declaratively, without blocking the main thread.

Main features:

  • Asynchronous execution: Allows launching tasks in a separate thread (or thread pool).
  • Composition: You can combine multiple CompletableFutures to create chains of dependent actions.
  • Exception handling: Provides methods for handling errors in asynchronous computations.
  • Non-blocking operations: The result or exception is processed when the future completes, without explicit waiting (get()).

Key methods:

  • Creation:
    • supplyAsync(Supplier<T> supplier): Runs the supplier asynchronously and returns a CompletableFuture with its result.
    • runAsync(Runnable runnable): Runs the runnable asynchronously and returns a CompletableFuture<Void>.
    • completedFuture(T value): Creates an already completed CompletableFuture with the given value.
  • Transformation:
    • thenApply(Function<T, U> fn): Applies a function to the result when the future completes.
    • thenAccept(Consumer<T> action): Performs an action on the result when the future completes.
    • thenRun(Runnable action): Performs an action when the future completes, ignoring the result.
    • thenCompose(Function<T, CompletionStage<U>> fn): Allows building chains where the result of one future is used to create another.
  • Combination:
    • thenCombine(CompletionStage<U> other, BiFunction<T, U, V> fn): Combines the results of two futures.
    • allOf(CompletableFuture<?>... cfs): Returns a CompletableFuture<Void> that completes when all the provided futures complete.
    • anyOf(CompletableFuture<?>... cfs): Returns a CompletableFuture<Object> that completes when any of the provided futures complete.
  • Exception handling:
    • exceptionally(Function<Throwable, T> fn): Handles exceptions, returning an alternative value.
    • handle(BiFunction<T, Throwable, U> fn): Handles both result and exception.

Example:

// Launching an asynchronous task
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(1000); // Simulate long work
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
    return "Result of asynchronous operation";
});

// Performing an action after task completion (non-blocking)
future.thenAccept(result -> {
    System.out.println("Received result: " + result);
});

// Another action depending on the first
future.thenApply(String::toUpperCase)
      .thenAccept(upperCaseResult -> {
          System.out.println("Result in uppercase: " + upperCaseResult);
      });

// Waiting for all tasks (usually avoided with explicit get/join in real applications)
// future.join();

CompletableFuture is a powerful tool for writing reactive and non-blocking code in Java, greatly simplifying asynchronous work compared to the classic Future interface.