Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java 9에서 CompletableFuture와 Future의 차이점 완벽 정리

CompletableFuture<T> 클래스는 Java에서 Future<T> 인터페이스를 구현한 클래스입니다. CompletableFuture는 명시적으로 완료된 상태의 Future처럼 사용할 수도 있습니다.

Future 인터페이스의 한계

Future 인터페이스는 제공하는 기능이 많지 않습니다. 비동기 연산의 결과를 얻으려면 블로킹(blocking) 방식으로 동작하는 get() 메서드를 호출해야 하며, 결과가 준비될 때까지 호출 스레드가 대기하게 됩니다. 이 때문에 여러 개의 의존적인 작업을 논블로킹(non-blocking) 방식으로 실행하기 어렵다는 단점이 있습니다.

CompletableFuture의 장점

반면 CompletableFuture 클래스는 여러 의존 작업을 비동기적으로 연결(chaining)할 수 있는 기능을 제공합니다. 즉, 현재 작업의 결과가 사용 가능해지는 시점에 다음 작업이 자동으로 트리거되는 작업 체인을 손쉽게 구성할 수 있습니다. thenAccept(), thenApply(), thenCompose() 같은 메서드를 활용하면 콜백 기반의 유연한 비동기 흐름 제어가 가능합니다.

문법(Syntax)

public class CompletableFuture<T> extends Object implements Future<T>, CompletionStage<T>

예제 코드

import java.util.function.Supplier;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureTest {
    public static void main(String args[]) throws ExecutionException, InterruptedException {
        Calculator calc = new Calculator(4, 7);
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(calc);
        future.thenAccept(result -> {
            System.out.println(result);
        });
        System.out.println("CompletableFutureTest End.... ");
        Thread.sleep(10000);
    }
}

// Calculator 클래스
class Calculator implements Supplier<Integer> {
    private int x, y;
    public Calculator(int x, int y) {
        this.x = x;
        this.y = y;
    }
    @Override
    public Integer get() {
        try {
            Thread.sleep(3000);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        return x + y;
    }
}

실행 결과

CompletableFutureTest End....
11

동작 원리 설명

supplyAsync(calc)는 Calculator 작업을 내부의 공용 스레드 풀(ForkJoinPool.commonPool)에 제출하여 비동기로 실행합니다. 따라서 메인 스레드는 계산이 끝날 때까지 기다리지 않고 곧바로 "CompletableFutureTest End...."를 출력합니다. 약 3초 후 계산이 완료되면 thenAccept()에 등록된 콜백이 실행되어 결과 값 11(4 + 7)이 출력됩니다. 이처럼 CompletableFuture를 사용하면 블로킹 없이 비동기 작업의 완료 시점에 후속 작업을 자연스럽게 연결할 수 있습니다.