0Pricing
Java Academy · 강의

퓨처 결합: allOf와 anyOf

allOf로 모든 퓨처를 기다리고 anyOf로 먼저 완료되는 작업을 선택해 시간 제한과 대체 처리 로직을 구현합니다.

퓨처 결합: allOf와 anyOf은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

퓨처를 결합하는 이유

서로 독립적인 비동기 작업을 병렬로 실행할 수 있다면, 다음 단계로 진행하기 전에 모든 작업 또는 첫 번째 작업이 완료될 때까지 기다리고 싶을 것입니다. allOf와 anyOf가 두 경우를 모두 처리합니다.

allOf: 모든 퓨처 대기

CompletableFuture.allOf(futures...)는 모든 입력 퓨처가 완료될 때 완료되는 CompletableFuture<Void>를 반환합니다. 하나라도 실패하면 allOf도 실패합니다.

CompletableFuture<String> f1 = fetchUserAsync();
CompletableFuture<List<Order>> f2 = fetchOrdersAsync();
CompletableFuture<Double> f3 = fetchBalanceAsync();
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);
all.join(); // wait for all three
String user   = f1.join();
List<Order> orders = f2.join();
Double balance = f3.join();

allOf 결과 수집

allOf는 Void를 반환하므로, allOf.join() 이후 각 개별 퓨처에서 join()을 호출하여 결과를 수집하십시오.

List<CompletableFuture<String>> futures = List.of(
    fetchAsync("url1"), fetchAsync("url2"), fetchAsync("url3"));
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
    .thenApply(v -> futures.stream()
        .map(CompletableFuture::join)
        .collect(Collectors.toList()))
    .thenAccept(results -> results.forEach(System.out::println))
    .join();

anyOf: 먼저 완료된 작업의 승리

CompletableFuture.anyOf(futures...)는 유형과 관계없이 가장 먼저 완료된 퓨처의 결과로 완료되는 CompletableFuture<Object>를 반환합니다.

CompletableFuture<Object> first = CompletableFuture.anyOf(
    fetchFromCacheAsync(),
    fetchFromDbAsync(),
    fetchFromApiAsync()
);
System.out.println("Fastest result: " + first.join());

시간 초과 대체 처리를 위한 anyOf

실제 계산과 시간 초과 퓨처를 경쟁시키십시오. 먼저 완료되는 쪽이 승리하므로 비블로킹 시간 초과 패턴을 구현할 수 있습니다.

CompletableFuture<String> real    = fetchDataAsync();
CompletableFuture<String> timeout = CompletableFuture
    .supplyAsync(() -> {
        try { Thread.sleep(2000); } catch (InterruptedException e) {}
        return "timeout-default";
    });
String result = (String) CompletableFuture.anyOf(real, timeout).join();

orTimeout(Java 9 이상)

orTimeout(time, unit)은 정해진 시간 안에 완료되지 않으면 TimeoutException으로 퓨처를 완료합니다. 수동으로 anyOf와 시간 초과를 조합하는 패턴보다 깔끔합니다.

CompletableFuture<String> result = fetchDataAsync()
    .orTimeout(3, TimeUnit.SECONDS)
    .exceptionally(ex -> "timeout-default");
System.out.println(result.join());

allOf를 사용한 병렬 HTTP 호출

여러 서비스로 동시에 요청을 보낸 다음 결과를 결합하십시오. 서비스가 서로 독립적일 때 순차 호출보다 훨씬 빠릅니다.

List<String> urls = List.of(url1, url2, url3);
List<CompletableFuture<String>> futures = urls.stream()
    .map(url -> CompletableFuture.supplyAsync(() -> httpGet(url)))
    .collect(Collectors.toList());
List<String> responses = CompletableFuture
    .allOf(futures.toArray(new CompletableFuture[0]))
    .thenApply(v -> futures.stream().map(CompletableFuture::join).collect(Collectors.toList()))
    .join();

allOf의 오류 처리

allOf의 퓨처 중 하나가 실패하면 반환된 퓨처도 즉시 실패합니다. 하나의 실패로 전체 묶음이 실패하지 않도록 개별 퓨처를 exceptionally로 감싸십시오.

List<CompletableFuture<String>> safe = futures.stream()
    .map(f -> f.exceptionally(ex -> "ERROR: " + ex.getMessage()))
    .collect(Collectors.toList());
CompletableFuture.allOf(safe.toArray(new CompletableFuture[0])).join();

서로 다른 유형과 함께 사용하는 allOf

allOf는 서로 다른 유형의 퓨처를 받을 수 있습니다. 결합한 후 각 퓨처의 결과를 예상 유형으로 변환하십시오.

CompletableFuture<User> userFuture   = fetchUser(id);
CompletableFuture<Config> configFuture = fetchConfig();
CompletableFuture.allOf(userFuture, configFuture).join();
User   user   = userFuture.join();
Config config = configFuture.join();

allOf와 thenApply 조합

모든 퓨처가 완료되는 즉시 결과를 집계하려면 allOf에 thenApply를 연결하십시오.

CompletableFuture<String> summary =
    CompletableFuture.allOf(f1, f2, f3)
        .thenApply(v -> "User: " + f1.join() +
                       ", Orders: " + f2.join().size() +
                       ", Balance: " + f3.join());
System.out.println(summary.join());

스레드 풀 고려 사항

allOf 또는 anyOf 호출에 포함된 모든 퓨처는 동시에 실행될 수 있습니다. 스레드 풀이 충분한 스레드를 갖추었는지 확인하거나 가상 스레드(Java 21 이상)를 사용하여 기아 상태를 방지하십시오.

// With virtual threads (Java 21+):
ExecutorService vt = Executors.newVirtualThreadPerTaskExecutor();
CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> httpGet(url), vt);

취소 전파

allOf와 anyOf는 하나가 완료되거나 취소되었을 때 남은 퓨처를 자동으로 취소하지 않습니다. 필요하면 각각 개별적으로 취소하십시오.

CompletableFuture<Object> first = CompletableFuture.anyOf(f1, f2, f3);
first.thenRun(() -> Stream.of(f1, f2, f3).forEach(f -> f.cancel(true)));

빠른 확인

CompletableFuture.anyOf는 무엇을 반환합니까?

복습

allOf는 모든 퓨처를 기다립니다(여러 작업을 모아 합치기). anyOf는 첫 번째 결과를 선택합니다(경쟁). 시간 초과에는 orTimeout을 사용하십시오. 하나의 실패로 전체 묶음이 실패하지 않도록 개별 퓨처를 exceptionally로 감싸십시오.

자주 묻는 질문

“퓨처 결합: allOf와 anyOf” 강의는 무료인가요?

네 — “퓨처 결합: allOf와 anyOf” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“퓨처 결합: allOf와 anyOf”에서 뭘 배우나요?

allOf로 모든 퓨처를 기다리고 anyOf로 먼저 완료되는 작업을 선택해 시간 제한과 대체 처리 로직을 구현합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“퓨처 결합: allOf와 anyOf” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. CompletableFutures 생성과 완료
  2. thenApply와 thenCompose를 사용한 연결
  3. 퓨처 결합: allOf와 anyOf
  4. 오류 처리와 비동기 HTTP 파이프라인
← Java Academy(으)로 돌아가기