- 외부에서 완료 불가
- 블로킹 코드인 get 으로만 이후의 결과를 처리 가능
- 여러 Future를 조합할 수 없음, 즉 활용도가 매우 떨어짐
- 예외 처리 불가
- EX) 몇 초 이내 응답 안오면 기본값 반환
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("Thread: " + Thread.currentThread().getName());
});
future.get();
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread: " + Thread.currentThread().getName());
return "Thread";
});
future.get();
// 쓰레드 1개인 ExecutorService를 리턴
ExecutorService executorService = Executors.newSingleThreadExecutor();
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "Thread: " + Thread.currentThread().getName();
}, executorService);
System.out.println(future.get());
System.out.println("Thread: " + Thread.currentThread().getName());
executorService.shutdown();
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "thread: " + Thread.currentThread().getName();
}).thenApply(s -> {
return s.toUpperCase();
});
System.out.println(future.get()); // 위 문자열 대문자로 리턴
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
return "Thread: " + Thread.currentThread().getName();
}).thenAccept((s)->{
System.out.println("End: " + s);
// return 없다.
});
future.get();
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
return "1st Thread: " + Thread.currentThread().getName();
}).thenRun(()->{
System.out.println("2nd Thread " + Thread.currentThread().getName());
});
future.get();
public class Compose {
public static void main(String[] args) throws InterruptedException, ExecutionException {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName());
return "Thread1";
});
CompletableFuture<String> future2 = future1.thenCompose(Compose::getCompose);
System.out.println(future2.get());
}
private static CompletableFuture<String> getCompose(String message) {
return CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName());
return message + " compose";
});
}
}
// ForkJoinPool.commonPool-worker-1
// ForkJoinPool.commonPool-worker-2
// Thread1 compose
CompletableFuture<String> thread1 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread1 " + Thread.currentThread().getName());
return "Thread1";
});
CompletableFuture<String> thread2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread2 " + Thread.currentThread().getName());
return "Thread2";
});
CompletableFuture<String> result = thread1.thenCombine(thread2, (i, j) -> i + " " + j);
System.out.println(result.get());
CompletableFuture<String> thread1 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread1 " + Thread.currentThread().getName());
return "Thread1";
});
CompletableFuture<String> thread2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread2 " + Thread.currentThread().getName());
return "Thread2";
});
List<CompletableFuture<String>> futures = Arrays.asList(thread1, thread2);
CompletableFuture<List<String>> results =
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]))
.thenApply(v -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
results.get().forEach(System.out::println);
CompletableFuture<String> thread1 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread1 " + Thread.currentThread().getName());
return "Thread1";
});
CompletableFuture<String> thread2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread2 " + Thread.currentThread().getName());
return "Thread2";
});
CompletableFuture<Void> future = CompletableFuture.anyOf(thread1, thread2).thenAccept(System.out::println);
future.get();
@ParameterizedTest
@ValueSource(booleans = {true, false})
void exceptionally(boolean doThrow) throws ExecutionException, InterruptedException {
CompletableFuture<String> thread = CompletableFuture.supplyAsync(() -> {
if (doThrow) {
throw new IllegalArgumentException("Invalid Argument");
}
return "Thread: " + Thread.currentThread().getName();
}).exceptionally(e -> {
return e.getMessage();
});
System.out.println(thread.get());
}
// True:
java.lang.IllegalArgumentException: Invalid Argument
// False:
// Thread: ForkJoinPool.commonPool-worker-2
@ParameterizedTest
@ValueSource(booleans = {true, false})
void handle(boolean doThrow) throws ExecutionException, InterruptedException {
CompletableFuture<String> thread = CompletableFuture.supplyAsync(() -> {
if (doThrow) {
throw new IllegalArgumentException("Invalid Argument");
}
return "Thread: " + Thread.currentThread().getName();
}).handle((result, e) -> {
return e == null ? result : e.getMessage();
});
System.out.println(thread.get());
}
public interface BiFuncton<T, U, R> {
R apply(T t, U u);
}
Reference: