Asynchronous Thread Processing in Java
1. Real-World Scenario: Order Processing System
Scenario: When a user places an order on an e-commerce platform, the system needs to:
1. Validate payment
2. Check inventory
3. Send confirmation email
4. Log the order
These tasks should be executed asynchronously to improve performance and user
experience.
2. Solution: Using CompletableFuture
The following code shows how to process the tasks asynchronously using
CompletableFuture:
ExecutorService executor = Executors.newFixedThreadPool(4);
CompletableFuture<Void> future = CompletableFuture
.supplyAsync(() -> validatePayment(orderId), executor)
.thenCombineAsync(CompletableFuture.supplyAsync(() ->
checkInventory(orderId), executor),
(paymentStatus, inventoryStatus) -> {
if (!paymentStatus || !inventoryStatus) {
throw new RuntimeException("Payment or Inventory check
failed.");
}
return orderId;
}, executor)
.thenAcceptAsync(OrderService::sendEmailConfirmation,
executor)
.thenRunAsync(() -> logOrder(orderId), executor)
.exceptionally(ex -> {
System.out.println("Order failed: " + ex.getMessage());
return null;
});
future.join();
executor.shutdown();
3. Bonus: Advanced Async Techniques
🔹 Custom Thread Pool + CompletableFuture:
- Provides control over threads.
- Prevents overloading ForkJoinPool.
🔹 ForkJoinPool:
- Efficient for recursive or CPU-bound tasks.
- Uses work-stealing for load balancing.
🔹 Spring’s @Async + TaskExecutor:
- Declarative async processing.
- Integrates easily with Spring Boot apps.
🔹 Reactive Streams (Project Reactor):
- Ideal for non-blocking I/O and high-concurrency applications.
- Uses Mono/Flux to handle streams of data reactively.
4. Diagram: Comparing Async Techniques