PHpullh
학습 라이브러리/Java/CompletableFuture — 비동기 프로그래밍

JAVA · 비동기/동시성

CompletableFuture — 비동기 프로그래밍

Java 8의 CompletableFuture로 비동기 작업을 조합하고 체이닝합니다.

비동기/동시성중급CompletableFuturesupplyAsyncthenApplythenComposeallOf

핵심 설명

Java 8의 CompletableFuture로 비동기 작업을 조합하고 체이닝합니다.

Java code

import java.util.concurrent.*;
import java.util.List;

public class AsyncDemo {

    static CompletableFuture<String> fetchUser(int id) {
        return CompletableFuture.supplyAsync(() -> {
            sleep(100);
            return "User#" + id;
        });
    }

    static CompletableFuture<String> fetchOrders(String userId) {
        return CompletableFuture.supplyAsync(() -> {
            sleep(100);
            return "Orders of " + userId;
        });
    }

    public static void main(String[] args) throws Exception {
        // thenApply — 변환 (Function)
        CompletableFuture<String> upper = fetchUser(1)
            .thenApply(String::toUpperCase);

        // thenAccept — 소비 (Consumer)
        fetchUser(1).thenAccept(u ->
            System.out.println("받음: " + u));

        // thenCompose — 플랫맵 (다른 CF 반환)
        CompletableFuture<String> orders = fetchUser(1)
            .thenCompose(AsyncDemo::fetchOrders);

        // thenCombine — 두 CF 결과 합치기
        CompletableFuture<String> combined =
            fetchUser(1).thenCombine(fetchUser(2),
                (u1, u2) -> u1 + " & " + u2);

        // allOf — 모두 완료 대기
        CompletableFuture<Void> all = CompletableFuture.allOf(
            fetchUser(1), fetchUser(2), fetchUser(3));
        all.join();

        // anyOf — 가장 빠른 것
        CompletableFuture<Object> any = CompletableFuture.anyOf(
            fetchUser(1), fetchUser(2));

        // 예외 처리
        CompletableFuture<String> safe = fetchUser(-1)
            .exceptionally(ex -> "기본 사용자")
            .handle((result, ex) -> {
                if (ex != null) return "에러: " + ex.getMessage();
                return result;
            });

        System.out.println(orders.get());
        System.out.println(combined.get());
        System.out.println(safe.get());
    }

    static void sleep(long ms) {
        try { Thread.sleep(ms); } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

학습 팁

thenApply()thenApplyAsync()의 차이: 전자는 이전 스테이지와 같은 스레드에서, 후자는 ForkJoinPool에서 실행됩니다.

주의할 점

CompletableFuture.get()은 체크드 예외를 던집니다. 더 간단한 .join()을 사용하면 unchecked exception으로 래핑됩니다.

자주 묻는 질문

CompletableFuture — 비동기 프로그래밍란 무엇인가요?

Java 8의 CompletableFuture로 비동기 작업을 조합하고 체이닝합니다.

CompletableFuture — 비동기 프로그래밍 학습 시 주의할 점은 무엇인가요?

CompletableFuture.get() 은 체크드 예외를 던집니다. 더 간단한 .join() 을 사용하면 unchecked exception으로 래핑됩니다.