일반적으로 Java나 Kotlin 비동기로 처리된 작업의 결과를 얻고자 하면 어떻게 하는가?
Future 객체를 사용할 수 있다.
ThreadExecutor에서 submit() 메서드를 사용하고 Callable 인터페이스를 통해 작업(Task)을 생성할 수 있다.
이 때 반환타입이 Future가 되는데, sum 메서드를 하나 생성 후 요청해보자.
fun sum(a: Int, b: Int) = a + b
fun main() {
val pool = Executors.newSingleThreadExecutor()
val future = pool.submit(Callable {
sum(100, 200)
})
println("계산 시작")
val futureResult = future.get() //비동기 작업의 결과를 기다린다.
println(futureResult)
println("계산 종료")
}
비동기라고는 했지만... Future에서 get()을 호출할 때, 결과가 반환되기 전까지 대기하게 된다.
Future는 비동기 작업에 대한 결과를 반환받을 수 있기는 하지만, 몇가지 문제가 있다.
- 외부에서 완료시킬 수 없다.
- blocking code인 get()을 통해서만 결과를 처리할 수 있다.
- 여러개의 Future를 조합할 수 없다.
- 예외 처리할 수 없다.
이러한 문제를 극복하기 위해 CompletableFuture가 등장하게 된다.
언제나 코드 먼저
fun main() {
val completableFuture = CompletableFuture.supplyAsync {
Thread.sleep(2000)
sum(100, 200)
}
println("계산 시작")
completableFuture.thenApplyAsync(::println) //논블로킹으로 동작
while (!completableFuture.isDone) {
Thread.sleep(500)
println("계산 결과를 집계 중입니다.")
}
println("계산 종료")
}
마찬가지로 sum() 메서드를 호출한다. 다반 supplyAsync 를 통해 비동기 작업을 수행한다.
이후 thenApplyAsync 를 통해 반환값을 받아 새로운 비동기 작업을 수행한다.
isDone을 통해 작업이 완료되었는지를 체크할 수 있다.
CompletableFuture는 훨씬 더 많은 기능을 제공한다.
예외 처리 기능, 응답의 결과를 결합 등 우아하게 비동기 처리가 가능하며, Future와 마찬가지로 get도 가능하다.
일단은 비동기에 대한 정리가 위주이기 때문에 CompletableFuture 자체의 기능에 대해서는 추후에 알아보도록 하자.
다음에는 비동기 방식을 처리하는 접근방식인 리액티브 프로그래임에 대해 정리하고자 한다.
출처 : 실무 프로젝트로 배우는 Kotlin & Spring : 리팩토링부터 서비스 구현까지, 패스트캠퍼스 (https://fastcampus.co.kr/courses/211160)
커리어 성장을 위한 최고의 실무교육 아카데미 | 패스트캠퍼스
성인 교육 서비스 기업, 패스트캠퍼스는 개인과 조직의 실질적인 '업(業)'의 성장을 돕고자 모든 종류의 교육 콘텐츠 서비스를 제공하는 대한민국 No. 1 교육 서비스 회사입니다.
fastcampus.co.kr