CompletableFuture
CompletableFunture은 Asynchronous programming을 수행할수 있도록 java에서 제공하는 class이며,
기존 Future를 기반으로 외부에서 완료시킬수 있어 CompletableFuture라는 이름을 갖게 되었다.
CompletableFuture은 Future에서 할수없었던 여러 Future의 조합, 예외처리, callback 등록 등이 가능하다.
비동기 작업
runAsync
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("runAsync");
});
future.get();
System.out.println("main");
runAsync는 반환값이 없으므로 Void타입이고, 위 코드를 실행해보면 future가 별도의 쓰레드에서 실행이 된다.
supplyAsync
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello, CompletableFuture!";
});
System.out.println("Before calling get()");
String result = future.get();
System.out.println("After calling get(): " + result);
supplyAsync는 runAsync와 달리 반환값이 존재한다. 따라서 비동기 작업의 결과를 받아올수 있다.
콜백
- thenApply, thenAccept, thenRun
- thenApply
- 반환 값을 받아 다른 값을 반환한다.
- 함수형 인터페이스 Function을 파라미터로 받는다
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "Hello, CompletableFuture!";
}).thenApply(s -> {
return s.toUpperCase();
});
System.out.println(future.get());
.thenApply를 통해 HELLO, COMPLETABLEFUTURE! 결과값을 얻을수 있다.
- thenAccept
- 반환 값을 받아 처리후 값을 반환하지 않는다.
- 함수형 인터페이스 Consumer를 파라미터로 받는다.
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
return "Hello, CompletableFuture!";
}).thenAccept(s -> {
System.out.println("thenAccept: " + s);
});
.thenAccept를 통해 thenAccept: Hello, CompletableFuture! 결과값을 얻을수 있다.
- thenRun
- 반환 값을 받지 않고 다른 작업을 실행한다.
- 함수형 인터페이스 Runnable을 파라미터로 받는다.
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
return "Hello, CompletableFuture!";
}).thenRun(() -> {
System.out.println("thenRun");
});
.thenRun()은 반환값을 받지않고 다른 작업을 실행하는 콜백이다. 위 코드 실행시 thenRun결과를 얻을수있다.
작업 조합
- thenCompose, thenCombine, allOf, anyOf
- thenCompose
- 두 작업이 이어서 실행하도록 조합, 앞선 작업의 결과를 받아 사용할수있다.
- 함수형 인터페이스 Function을 파라미터로 받는다.
CompletableFuture<String> future1 =
CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 =
future1.thenCompose(result ->
CompletableFuture.supplyAsync(() -> result + ", CompletableFuture!"));
System.out.println("Result of thenCompose: " + future2.get());
.thenCompose를 통해 Result of thenCompose: Hello, CompletableFuture! 다음과 같은 결과를 얻을수있다.
- thenCombine
- 두 작업을 독립적으로 실행한후, 둘다 완료되었을떄 콜백을 실행한다.
- 함수형 인터페이스 Function을 파라미터로 받는다.
CompletableFuture<String> future3 =
CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future4 =
CompletableFuture.supplyAsync(() -> ", CompletableFuture!");
CompletableFuture<String> combinedFuture =
future3.thenCombine(future4, (result1, result2) -> result1 + result2);
System.out.println("Result of thenCombine: " + combinedFuture.get());
thenCombine을 통해 독립적으로 실행된 future3과 future4의 결과를 조합해 future4에서 처리한다.
결과값은 Result of thenCombine: Hello, CompletableFuture!이다.
- allOf
- 여러 작업들을 동시에 실행하고, 모든 작업 결과에 콜백을 실행한다.
CompletableFuture<String> future5 =
CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future6 =
CompletableFuture.supplyAsync(() -> "CompletableFuture!");
List<CompletableFuture<String>> futures = List.of(future5, future6);
CompletableFuture<List<String>> result =
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]))
.thenApply(v -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
result.get().forEach(System.out::println);
allOf는 모든결과에 콜백이 적용되어 위 코드의 결과값이 아래와 같음을 알수있다.
Hello
CompletableFuture!
- anyOf
- 여러 작업들 중에서 가장 빨리 끝난 하나의 결과에 콜백을 실행한다.
CompletableFuture<String> future7 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello";
});
CompletableFuture<String> future8 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "CompletableFuture!";
});
CompletableFuture<Object> firstFuture = CompletableFuture.anyOf(future7, future8);
System.out.println("Result of anyOf: " + firstFuture.get());
anyOf는 future7과 future8중 더빨리끝난 하나의 결과에 콜백을 실행하므로 결과값은
Result of anyOf: Hello이다.
예외처리
- exceptionally
- 발생한 에러를 받아 예외를 처리한다.
- 함수형 인터페이스 Function을 파라미터로 받는다.
- handle,handleAsync
- (결과값,에러)를 반환받아 에러가 발생한 경우와 아닌 경우 모두를 처리할수있다.
- 함수형 인터페이스 BiFunction을 파라미터로 받는다.
Reference