CompletableFuture — 명시적으로 완료 가능한 비동기 퓨처

CompletableFuture — 명시적으로 완료 가능한 비동기 퓨처

CompletableFuture<T>명시적으로 완료(값과 상태를 설정)할 수 있는 Future이자, 완료 시 의존 함수·액션이 촉발되는 CompletionStage로 쓸 수 있게 해주는 클래스예요. 비동기 프로그래밍에서 "완료 시점에 이어서 할 일"을 체이닝하며 자유롭게 조합하고 싶을 때 핵심적으로 쓰여요.

출처: Java API Reference

본문

클래스 개요

CompletableFutureFuture이자 CompletionStage예요.

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

두 개 이상의 스레드가 같은 CompletableFuture에 대해 complete, completeExceptionally, cancel을 시도하면 하나만 성공해요.

실행 정책

  • 비동기 메서드의 기본 실행: 명시적 Executor 인자가 없는 모든 async 메서드는 ForkJoinPool.commonPool()에서 실행돼요(병렬 수준이 2 이상을 못 지원하면 태스크마다 새 Thread 생성). 비정적 메서드에 대해서는 서브클래스가 defaultExecutor()를 오버라이드해 바꿀 수 있어요.
  • 생성된 비동기 태스크는 모두 마커 인터페이스 CompletableFuture.AsynchronousCompletionTask의 인스턴스예요.
  • 시간 지연이 있는 연산은 어댑터 메서드를 쓸 수 있어요. 예: supplyAsync(supplier, delayedExecutor(timeout, timeUnit)).
  • 모든 CompletionStage 메서드는 다른 공개 메서드와 독립적으로 구현되어, 한 메서드의 동작이 서브클래스의 다른 메서드 오버라이드에 영향받지 않아요.
  • 모든 CompletionStage 메서드는 CompletableFuture를 반환해요. CompletionStage 인터페이스의 메서드만 쓰도록 제한하려면 minimalCompletionStage(), 클라이언트가 미래를 직접 수정하지 못하게 하려면 copy()를 써요.

Future 관점 정책

FutureTask와 달리 이 클래스는 완료를 일으키는 계산을 직접 제어하지 못하므로, 취소는 예외적 완료의 한 형태로 취급돼요. cancelcompleteExceptionally(new CancellationException())과 같은 효과예요. isCompletedExceptionally()로 어떤 예외적 방식으로 완료됐는지 판단할 수 있어요.

CompletionException으로 예외 완료된 경우 get()/get(long, TimeUnit)은 같은 cause를 가진 ExecutionException을 던져요. 대부분의 맥락에서 편리하게 쓰도록 join()getNow(T)는 이런 경우 CompletionException을 직접 던져요.

완료 결과를 전달하는 인자(타입 T 파라미터)는 null일 수 있지만, 다른 파라미터에 null을 넘기면 NullPointerException이 던져져요.

서브클래스 확장

CompletionStage 메서드가 반환하는 구체 타입을 정하는 "가상 생성자" newIncompleteFuture()를 보통 오버라이드해요. 예를 들어 기본 Executor를 바꾸고 obtrude 메서드를 비활성화하는 클래스:

class MyCompletableFuture<T> extends CompletableFuture<T> {
    static final Executor myExecutor = ...;
    public MyCompletableFuture() { }
    public <U> CompletableFuture<U> newIncompleteFuture() {
        return new MyCompletableFuture<U>(); }
    public Executor defaultExecutor() {
        return myExecutor; }
    public void obtrudeValue(T value) {
        throw new UnsupportedOperationException(); }
    public void obtrudeException(Throwable ex) {
        throw new UnsupportedOperationException(); }
}

생성자

public CompletableFuture() — 새롭고 완료되지 않은(incomplete) CompletableFuture를 만들어요.

정적 팩토리 메서드

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)ForkJoinPool.commonPool()에서 도는 태스크가 주어진 Supplier를 호출해 얻은 값으로 비동기적으로 완료되는 새 CompletableFuture를 반환해요. supplyAsync(supplier, executor) 변형이 있어요.

public static CompletableFuture<Void> runAsync(Runnable runnable)commonPool()의 태스크가 주어진 액션을 실행한 뒤 완료되는 새 퓨처를 반환해요. runAsync(runnable, executor) 변형이 있어요.

public static <U> CompletableFuture<U> completedFuture(U value) — 주어진 값으로 이미 완료된CompletableFuture를 반환해요.

public static <U> CompletionStage<U> completedStage(U value) — 주어진 값으로 이미 완료되고 CompletionStage의 메서드만 지원하는 새 단계를 반환해요. (JDK 9+)

public static <U> CompletableFuture<U> failedFuture(Throwable ex) — 주어진 예외로 이미 예외적으로 완료된 새 퓨처를 반환해요. (JDK 9+)

public static <U> CompletionStage<U> failedStage(Throwable ex) — 주어진 예외로 이미 예외적으로 완료된 CompletionStage를 반환해요. (JDK 9+)

상태·결과 조회 (Future 계열)

public boolean isDone() — 정상·예외·취소 중 어떤 방식으로든 완료됐으면 true.

public boolean isCancelled() — 정상 완료 전에 취소됐으면 true.

public boolean isCompletedExceptionally() — 취소, completeExceptionally 명시 호출, CompletionStage 액션의 급작 종료 등 어떤 방식으로든 예외적으로 완료됐으면 true.

public int getNumberOfDependents() — 이 퓨처의 완료를 기다리는 의존 CompletableFuture의 추정 개수를 반환해요. 동기화 제어가 아닌 시스템 상태 모니터링용이에요.

public String toString() — 이 퓨처와 완료 상태를 식별하는 문자열을 반환해요. 대괄호 안에 "Completed Normally", "Completed Exceptionally", 또는 "Not completed"(의존 수 포함)를 담아요.

결과 받기

public T get() throws InterruptedException, ExecutionException — 필요하면 완료될 때까지 기다린 뒤 결과를 반환해요.

  • CancellationException (취소), ExecutionException (예외 완료), InterruptedException

public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException — 최대 timeout까지 기다린 뒤 결과를 반환해요.

  • TimeoutException (대기 시간 초과) 등

public T join() — 완료되면 결과 값을 반환하거나, 예외적으로 완료됐으면 (비검사) 예외를 던져요. 완료 계산에서 예외가 나면 그 예외를 cause로 가진 (비검사) CompletionException을 던져요.

  • CancellationException, CompletionException

public T getNow(T valueIfAbsent) — 완료됐으면 결과 값을 반환(또는 만난 예외를 던지고), 완료되지 않았으면 valueIfAbsent를 반환해요.

  • CancellationException, CompletionException

완료시키기

public boolean complete(T value) — 아직 완료되지 않았다면 get()과 관련 메서드가 반환할 값을 주어진 값으로 설정해요. 이 호출이 완료 상태로 전이시켰으면 true.

public boolean completeExceptionally(Throwable ex) — 아직 완료되지 않았다면 get()과 관련 메서드가 주어진 예외를 던지게 해요. 성공 시 true.

public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier, Executor executor) — 주어진 executor의 비동기 태스크에서 Supplier를 호출한 결과로 이 퓨처를 완료해요. completeAsync(supplier)는 기본 executor를 써요. (JDK 9+)

public boolean cancel(boolean mayInterruptIfRunning) — 아직 완료되지 않았다면 CancellationException으로 이 퓨처를 완료해요. 이 구현에서 mayInterruptIfRunning은 효과가 없어요(인터럽트가 처리를 제어하지 않으므로).

public void obtrudeValue(T value) — 이미 완료됐는지와 무관하게 get()과 관련 메서드가 반환할 값을 강제로 설정/재설정해요. 오류 복구 액션 전용이며, 진행 중인 의존 완료가 기존 결과를 쓸지 덮어쓴 결과를 쓸지에 영향을 줄 수 있어요.

public void obtrudeException(Throwable ex) — 이미 완료됐는지와 무관하게 이후 get() 호출이 주어진 예외를 던지게 강제해요. NullPointerException — 예외가 null일 때.

타임아웃·지연 관련

public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit) — 주어진 시간 전에 다른 방식으로 완료되지 않으면 TimeoutException으로 예외적으로 완료해요. (JDK 9+)

public CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit) — 주어진 시간 전에 완료되지 않으면 주어진 value로 정상 완료해요. (JDK 9+)

public static Executor delayedExecutor(long delay, TimeUnit unit, Executor executor) — 주어진 지연(delay) 후(양수면 지연, 아니면 즉시) 태스크를 기본 executor에 제출하는 새 Executor를 반환해요. 지연은 반환된 executor의 execute 호출 시점부터 시작돼요. delayedExecutor(delay, unit)는 기본 executor를 써요. (JDK 9+)

결합·복제·제한

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) — 주어진 모든 CompletableFuture가 완료될 때 완료되는 새 퓨처를 반환해요. 어느 하나라도 예외적으로 완료되면 그 예외를 cause로 가진 CompletionException으로 완료돼요. 제공한 퓨처가 없으면 null 값으로 완료된 퓨처를 반환해요. 예: CompletableFuture.allOf(c1, c2, c3).join();

  • NullPointerException — 배열이나 원소가 null일 때

public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) — 주어진 CompletableFuture하나라도 완료되면 같은 결과로 완료되는 새 퓨처를 반환해요. 예외적으로 완료되면 그 예외를 cause로 가진 CompletionException으로 완료돼요. 제공한 퓨처가 없으면 완료되지 않은 퓨처를 반환해요.

  • NullPointerException

public CompletableFuture<T> copy() — 이 퓨처가 정상 완료되면 같은 값으로 정상 완료되는 새 퓨처를 반환해요. 예외 완료 시엔 이 예외를 cause로 가진 CompletionException으로 완료돼요. thenApply(x -> x)와 동등하며, 클라이언트가 완료하지 못하게 하는 "방어적 복사"로 유용해요. (JDK 9+)

public CompletionStage<T> minimalCompletionStage() — 정상 완료 시 같은 값으로 완료되고, CompletionStage의 메서드로 정의되지 않은 방식으로 독립 완료하거나 쓰일 수 없는 새 단계를 반환해요. 예외 완료 시 이 예외를 cause로 가진 CompletionException으로 완료돼요. (JDK 9+)

public <U> CompletableFuture<U> newIncompleteFuture() — CompletionStage 메서드가 반환할 타입의 새롭고 완료되지 않은 퓨처를 반환해요. 서브클래스 보통 오버라이드. (JDK 9+)

public Executor defaultExecutor() — Executor를 지정하지 않는 async 메서드에 쓰이는 기본 Executor를 반환해요. (JDK 9+)

CompletionStage 메서드

CompletableFutureCompletionStage의 모든 메서드(thenApply, thenAccept, thenRun, thenCombine, thenAcceptBoth, runAfterBoth, applyToEither, acceptEither, runAfterEither, thenCompose, handle, whenComplete, exceptionally, exceptionallyAsync, exceptionallyCompose, toCompletableFuture 등)를 구현해요. 각 메서드의 동작과 Async/Executor 변형 규칙은 CompletionStage 문서를 참고하세요. toCompletableFuture()는 이 CompletableFuture 자신을 반환해요.

더 알아보기 (Learn more)