본문으로 바로가기
반응형

Future 는 비동기 작업 수행의 결과를 담고있는 자바의 인터페이스이다.

ListenableFuture 는 Spring 에서 제공하는 인터페이스로 Future에 콜백을 등록해 사용할 수 있도록 한 방식이다.

자바 8 때 소개된 CompletableFuture 는 여러 비동기 작업을 결합하고 처리하는데 기존 방식에 비해 훨씬 편하게 수행할 수 있다.

아래는 간단히 반환값이 없는 2개 비동기 작업을 수행하는 예시이다.

CompletableFuture
	.runAsync(() -> log.info("runAsync"))
	.thenRun(() -> log.info("thenRun"));

반환값이 있는 비동기 작업은 아래와 같이 할 수 있다.

CompletableFuture
	.supplyAsync(() -> 1)  // 비동기적으로 값을 제공 (외부 API 호출 등)
	.thenApply(i -> i + "hi")  // 값을 가공
	.exceptionally(e -> e.getMessage()) // 작업 중 오류가 발생했을 경우 사용될 값
	.thenAccept(i -> System.out.println(i)); // 값을 사용

CompletableFuture 에서 할 수 있는 작업들은 CompletionStage 에 정의되어있다.

CompletableFuture 에서 수행되는 작업은 내부에 관리되는 ForkJoinPool에 의해 실행된다.

이때 ForkJoinPool의 병렬도가 1 이상이면 ForkJoinPool, 아니면 각 작업마다 하나의 스레드가 할당되는 ThreadPerTaskExecutor가 사용된다.

(풀 병렬도는 ForkJoinPool.getCommonPoolParallelism() 메소드로 가져오는데,, 이게 정확히 무슨 값을 의미하는지는 잘 모르겠음. 아시는 분 댓글 남겨주시길 바랍니다)

 

메소드 네이밍에 따라 *Async 로 호출되는 메소드는 두 번째 인자로 특정 스레드풀에서 실행되게 할 수도 있다.

 

만약 어떤 작업 내에서 리턴값이 CompletableFuture가 되어야하는 경우 thenCompose 를 사용한다.

이는 또다른 비동기 작업을 수행하되, CompletableFuture 타입이 아닌경우 CompletableFuture로 변환하여 리턴할 수 있다.

아래 예시는 스프링의 ListenableFuture를 중간작업으로 수행하는데 CompletableFuture 체인에 연결한 예시이다.

// Callback 방식의 ListenableFuture를 CompletableFuture로 변환해주는 메소드
// ListenableFuture 콜백에 CompletableFuture 방식의 메소드를 전달한다.
public static <T> toCompletableFuture(ListenableFuture<T> lf) {
    CompletableFuture<T> cf = new CompletableFuture<>();
    lf.addCallback(cf::complete, cf::completeExceptionally);
    return cf;
}
CompletableFuture
        .supplyAsync(() -> 1)
        .thenCompose(i -> {
            ListenableFuture<Integer> lf = doListenableFutureJob();            
            return toCompletableFuture(lf); // CompletableFuture 체인에 연결해주기위해 바꿔줌
        })
        .thenAccept(i -> System.out.println(i));
반응형