Java, asynchronous methods

In Java, asynchronous methods are methods that start a task and return immediately, allowing the program to continue executing without waiting for the task to finish. This is useful for I/O operations, network calls, or long-running computations.

Java provides several ways to implement asynchronous methods.


1️⃣ Using CompletableFuture (Java 8+)

The modern and recommended approach for asynchronous programming in Java is CompletableFuture.

import java.util.concurrent.CompletableFuture;

public class AsyncExample {
    public static void main(String[] args) {
        System.out.println("Start");

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // Simulate long-running task
            try { Thread.sleep(2000); } catch (InterruptedException e) {}
            return "Hello from async task";
        });

        // Do other work while async task runs
        System.out.println("Doing other work...");

        // Get result (blocks only here if needed)
        String result = future.join();
        System.out.println(result);
        System.out.println("End");
    }
}

Output:

Start
Doing other work...
Hello from async task
End
  • supplyAsync() → runs a task asynchronously and returns a CompletableFuture.
  • join() → waits for the result (similar to get() but wraps exceptions).

Chaining Asynchronous Tasks

CompletableFuture.supplyAsync(() -> "Hello")
                 .thenApply(s -> s + " World")
                 .thenAccept(System.out::println);
  • thenApply() → transforms the result
  • thenAccept() → consumes the result
  • Tasks are executed asynchronously, allowing non-blocking execution.

2️⃣ Using ExecutorService

import java.util.concurrent.*;

public class ExecutorExample {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Future<String> future = executor.submit(() -> {
            Thread.sleep(2000);
            return "Async Task Result";
        });

        System.out.println("Doing other work...");
        System.out.println(future.get());  // blocks until result is ready

        executor.shutdown();
    }
}
  • submit() → executes the task asynchronously and returns a Future.
  • get() → blocks until the task finishes.

3️⃣ Using @Async in Spring Framework

In Spring, you can annotate methods with @Async to run them asynchronously:

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncService {

    @Async
    public CompletableFuture<String> asyncMethod() throws InterruptedException {
        Thread.sleep(2000);
        return CompletableFuture.completedFuture("Hello from Spring Async");
    }
}
  • Requires @EnableAsync on a configuration class.
  • Spring handles the thread pool automatically.

4️⃣ Key Points

AspectNotes
Non-blockingAsynchronous methods allow the program to continue without waiting.
Return typeOften CompletableFuture<T> or Future<T>.
Thread managementCompletableFuture uses ForkJoinPool.commonPool() by default; ExecutorService allows custom thread pools.
Exception handlingUse handle(), exceptionally(), or whenComplete() for async error handling.
ChainingTasks can be chained using thenApply, thenCompose, thenAccept.

Summary

  • Asynchronous methods: Start a task and return immediately.
  • Java options:
    1. CompletableFuture (modern, flexible, supports chaining)
    2. ExecutorService / Future (classic)
    3. @Async in Spring (framework support for async execution)
  • Useful for network calls, database operations, and long computations.

Leave a Reply