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 aCompletableFuture.join()→ waits for the result (similar toget()but wraps exceptions).
✅ Chaining Asynchronous Tasks
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World")
.thenAccept(System.out::println);
thenApply()→ transforms the resultthenAccept()→ 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 aFuture.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
@EnableAsyncon a configuration class. - Spring handles the thread pool automatically.
4️⃣ Key Points
| Aspect | Notes |
|---|---|
| Non-blocking | Asynchronous methods allow the program to continue without waiting. |
| Return type | Often CompletableFuture<T> or Future<T>. |
| Thread management | CompletableFuture uses ForkJoinPool.commonPool() by default; ExecutorService allows custom thread pools. |
| Exception handling | Use handle(), exceptionally(), or whenComplete() for async error handling. |
| Chaining | Tasks can be chained using thenApply, thenCompose, thenAccept. |
✅ Summary
- Asynchronous methods: Start a task and return immediately.
- Java options:
CompletableFuture(modern, flexible, supports chaining)ExecutorService/Future(classic)@Asyncin Spring (framework support for async execution)
- Useful for network calls, database operations, and long computations.
