Java CompletableFuture: Async Programming แบบ Modern

#java13 เม.ย. 2569

CompletableFuture คืออะไร

CompletableFuture (Java 8+) ช่วยให้เขียน async code ได้ง่ายขึ้น รองรับ chaining, combining และ error handling

สร้าง CompletableFuture

import java.util.concurrent.CompletableFuture;

// runAsync - ไม่คืนค่า
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
    System.out.println("Running async...");
});

// supplyAsync - คืนค่า
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    return "Hello from async!";
});

String result = future2.get();  // block

Chaining

CompletableFuture<String> future = CompletableFuture
    .supplyAsync(() -> fetchUser(1))          // async fetch
    .thenApply(user -> user.getName())         // transform
    .thenApply(name -> "สวัสดี " + name)       // transform อีกครั้ง
    .thenApply(String::toUpperCase);

future.thenAccept(System.out::println);  // consume

Combining Futures

// thenCombine - รวม 2 futures
CompletableFuture<String> userFuture = CompletableFuture.supplyAsync(() -> fetchUser(1));
CompletableFuture<String> orderFuture = CompletableFuture.supplyAsync(() -> fetchOrders(1));

CompletableFuture<String> combined = userFuture.thenCombine(
    orderFuture,
    (user, orders) -> user + " has orders: " + orders
);

// allOf - รอทุก future
CompletableFuture<Void> all = CompletableFuture.allOf(
    userFuture, orderFuture
);
all.join();

// anyOf - รอ future แรกที่เสร็จ
CompletableFuture<Object> any = CompletableFuture.anyOf(
    userFuture, orderFuture
);

Error Handling

CompletableFuture<String> future = CompletableFuture
    .supplyAsync(() -> {
        if (Math.random() > 0.5) throw new RuntimeException("Error!");
        return "Success";
    })
    .exceptionally(ex -> {
        System.out.println("Error: " + ex.getMessage());
        return "Default value";
    })
    .handle((result, ex) -> {
        if (ex != null) return "Error occurred";
        return result.toUpperCase();
    });

ตัวอย่างจริง

public CompletableFuture<UserProfile> getUserProfile(int userId) {
    CompletableFuture<User> userFuture =
        CompletableFuture.supplyAsync(() -> userService.findById(userId));

    CompletableFuture<List<Order>> ordersFuture =
        CompletableFuture.supplyAsync(() -> orderService.findByUserId(userId));

    CompletableFuture<List<Review>> reviewsFuture =
        CompletableFuture.supplyAsync(() -> reviewService.findByUserId(userId));

    return CompletableFuture.allOf(userFuture, ordersFuture, reviewsFuture)
        .thenApply(v -> new UserProfile(
            userFuture.join(),
            ordersFuture.join(),
            reviewsFuture.join()
        ));
}

สรุป

CompletableFuture ทำให้เขียน async code ใน Java ได้ง่ายขึ้นมาก รองรับ chaining, combining และ error handling ที่ดี เหมาะกับ I/O-intensive operations ครับ