퓨처 결합: 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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- CompletableFutures 생성과 완료
- thenApply와 thenCompose를 사용한 연결
- 퓨처 결합: allOf와 anyOf
- 오류 처리와 비동기 HTTP 파이프라인