작성
·
450
2
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(() -> "hello!");
String res = future.get();
res = res.toUpperCase();
vs
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("hello world! " + Thread.currentThread().getName());
return "I'm Kang";
}).thenApply(s -> {
System.out.println(Thread.currentThread().getName());
return s.toUpperCase();
});
System.out.println(future.get());
안녕하세요 강의 잘 듣고있습니다!
1분 50초 ~ 2분 5초까지 말씀하시길
일반적으로 아래와 같은 callback 방식이 다른 언어에서 작성하는 코딩 패턴이라고 말씀하셨습니다.
다만 저에게 있어 위 코드와 아래 코드가 동작하는 방식이 동일한 것 같고 (어찌 됐든 둘 다 get에서 blocking이 될 테니 말이죠) 그러다 보니 Callback을 사용하는 장점을 잘 이해하지 못했습니다. 조금 더 다채로운 상황에서 Callback을 사용할 때 유리한 점이 있다면 소개해 주실 수 있을까요?
답변 1
8
안녕하세요. edu님 좋은 질문 감사합니다.
둘다 get() 호출시 blocking이 된다는 사실은 말씀하신대로 차이가 없지만 CompletableFuture은 다른 Future를 조합할 수 있다는 장점이 있어요. 그 조합하는 방법이 마치 함수형 프로그래밍 언어와 비슷하기 때문에 자바스크립와 같은 다른 언어의 코딩 패턴과 비슷하다고 언급한 겁니다.
thenApply나 thenCompose등으로 여러 Future를 (원한다면 비동기적으로도) 조합해서 사용하는데 있어 큰 장점을 느끼지 못한다면 Future만 쓰셔도 좋습니다. 나중에 여러 작업들이 복잡하게 이어지는 코드를 작성해야 할 때 CompletableFuture의 필요성을 느낄 수 있을 겁니다.
가령, 회원 목록을 가져오고, 스터디 목록을 가져와서, 회원 중에 스터디에 참여하지 않았던 사람들을 추리고, 각 회원에게 추천 스터디 목록을 가져온 다음, 추천 스터디를 이메일로 전송하는 로직이라면 이 중에 일부는 비동기적으로 동시에 처리할 수도 있고 일부는 순차적으로 이어져야 하는데 그런것들을 CompletableFuture가 제공하는 메소드로 잘 표현할 수 있다는 장점이 있습니다.