CompletableFuture란?
- 자바에서 비동기(Asynchronous) 프로그래밍을 가능하게 하는 인터페이스
- 일반적인 Future 사용시 제약이 많았음
Future 단점
- 외부에서 Future를 완료시킬 수 없다.
- 취소하거나 get()에 타임아웃을 설정할 수 는 있다.
- 블록킹 코드( get() )을 사용하지 않고서는 작업이 끝났을 때 콜백을 실행할 수 없다.
- 여러 Future를 조합할 수 없다.
- 예외처리용 API를 제공하지 않는다.
CompletableFuture
- 두가지 인터페이스를 구현하고 있다.
- Implements Future
- Implements CompletionStage
- 외부에서 명시적으로 완료시켜버릴 수 있다.
- 예를 들어 몇초 이내 응답이 안오면 기본 값으로 미리 세팅해둔 값을 리턴하도록 만들 수 있다.
- 명시적으로 ExecutorService를 만들어 쓸 필요가 없고, CompletableFuture만 가지고 비동기적으로 어떤 작업들을 실행할 수 있다.
- get()을 호출하지 않으면 아무 일도 일어나지 않는다.
비동기로 작업 실행
- 리턴 값 없는 경우 : runAsync()
- 리턴 값 있는 경우 : supplyAsync()
- 원하는 Executor(쓰레드풀)을 사용하여 실행할 수 있다. (기본은 ForkJoinPool.commonPool() 이고, runAsync() 혹은 supplyAsync()의 두번째 파라미터로 전달하면 된다.)
public static void main(String[] args) throws ExecutionException, interruptedException {
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
System.out.println("Hello " + Thread.currentThread().getName());
});
future1.get();
/* 출력
Hello ForkJoinPool.commonPool-worker-3
*/
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Hello " + Thread.currentThread().getName());
return "Hello";
});
System.out.println(future2.get());
/* 출력
Hello ForkJoinPool.commonPool-worker-3
Hello
*/
}
콜백 제공
- 콜백도 원하는 Executor(쓰레드풀)을 사용하여 실행할 수 있다. (기본은 ForkJoinPool.commonPool() 이고, thenApply(), thenAccept(), thenRun()의 두번째 파라미터로 전달하면 된다.)
- thenApply(Function) : 리턴값을 받아 다른 값으로 바꾸는 콜백
//thenApply
public static void main(String[] args) throws ExecutionException, interruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("Hello " + Thread.currentThread().getName());
return "Hello";
}).thenApply((s) -> { //리턴값을 받아
System.out.println(Thread.currentThread().getName());
return s.toUpperCase(); //다른 값으로 바꾸어 콜백
});
System.out.println(future.get());
}
/* 출력
Hello ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-3
HELLO
*/
- thenAccept(Consumer) : 리턴값을 받아 다른 작업을 하는 콜백(다른 작업을 처리할 때는 리턴하지 않는다)
//thenAccept
public static void main(String[] args) throws ExecutionException, interruptedException {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
System.out.println("Hello " + Thread.currentThread().getName());
return "Hello";
}).thenApply((s) -> { //리턴값을 받아
System.out.println(Thread.currentThread().getName());
System.out.println(s.toUpperCase()); //다른 작업을 하는 콜백(리턴은 하지 않음)
});
future.get();
}
/* 출력
Hello ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-3
HELLO
*/
- thenRun(Runnable) : 리턴값을 받지 않고 다른 작업을 하는 콜백(사실상 runnable과 같음)
//thenRun (그냥 runnable이 오는 것과 같음)
public static void main(String[] args) throws ExecutionException, interruptedException {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
System.out.println("Hello " + Thread.currentThread().getName());
return "Hello";
}).thenApply(() -> { //리턴값을 받지 않고
System.out.println(Thread.currentThread().getName());//다른 작업을 하는 콜백(리턴도 하지 않음)
});
future.get();
}
/* 출력
Hello ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-3
*/
조합하기
- thenCompose() : A 의 결과를 받아 B 작업이 이어서 실행되도록 조합(서로 연관 관계가 있는 경우)
- thenCombine() : 두 작업을 독립적으로(비동기로) 실행하고, 둘 다 종료되었을 때 콜백 실행(서로 연관 관계가 없는 경우)
- allOf() : 여러(두개 이상) 작업을 모두 실행하고 모든 작업 결과에 콜백 실행
- 모든 작업들의 결과가 동일한 타입이라는 보장도 없고 에러가 발생하는 작업이 생길 수 도 있다.
- anyOf() : 여러 작업중에 가장 빨리 끝난 하나의 결과에 콜백 실행
예외 처리
- exceptionally(Function)
- handle(BiFunction)
이 포스팅은 더 자바, Java 8 강의를 수강하며 작성되었습니다.
더 자바, Java 8 강의 | 백기선 - 인프런
백기선 | 자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합
www.inflearn.com
'Java' 카테고리의 다른 글
[Java8] 배열 병렬 정렬 (0) | 2024.09.03 |
---|---|
[Java8] Annotation의 변화 (0) | 2024.09.02 |
[Java8] Callable과 Future (0) | 2024.08.29 |
[Java8] Executors (0) | 2024.08.28 |
[Java8] Concurrent Programming (0) | 2024.08.27 |