You will be fine

<Java> CompletableFuture

by BFine
반응형

가. 비동기 처리에 결과를 또 사용해야 하는데.. 

 a. FutureTask 예제

public static void main(String[] args) throws InterruptedException, ExecutionException {

    ExecutorService executorService = Executors.newSingleThreadExecutor();


    Future<String> submit1 = executorService.submit(()->addWord("","hello"));
    final String hello = submit1.get();
    System.out.println(hello+" "+Thread.currentThread());

    Future<String> submit2 = executorService.submit(()->addWord(hello,"world"));
    final String helloWorld = submit2.get();
    System.out.println(helloWorld+" "+Thread.currentThread());

    Future<String> submit3 = executorService.submit(()->addWord(helloWorld,"happy"));
    final String helloWorldHappy = submit3.get();
    System.out.println(helloWorldHappy+" "+Thread.currentThread());

    executorService.shutdownNow();
}

public static String addWord(String target, String word){
    System.out.println(word +" 추가 " + Thread.currentThread());
    return target+" "+word;
}

  -  비동기 처리한 결과 데이터를 이용해서 또 비동기 처리해야하는 경우를 만들어 보았다. 불필요하게 Main 스레드에서 .get() 하고 있는 것을 볼 수 있다.

  -  비동기 처리를 위한 비슷한 부가적인 코드들이 생겨 로직이 지저분해졌다.
      => Spring 에서는 ListenableFuture 에서 Callback 지원하지만 이런 처리가 많아질수록 Callback Hell이 발생한다.

 

나. CompletableFuture 란

 a. 무엇인가?

  -  java 8 부터 추가된 Future의 구현체로 위의 문제를 CompletionStage를 통해 chain 형태로 해결할 수 있다. 

 

 b. CompletionStage 

  -  이 인터페이스는 비동기 처리 및 후 처리를 위한 다양한 메서드들을 보유하고 있다.

  -  이를 구현하고 있는 CompletableFuture 메서드들을 살펴보면 CompletableFuture 자체를 return으로 사용하는 것을 볼 수 있다.

  - 위의 코드를 살펴보면 CompleteFuture 를 생성하고 여기에 결과(or 실행)을 담고 생성한 CompleteFuture 자체를 반환하고 있다.  

  - 즉 CompletionStage는 자기자신의 참조를 통해 비동기 연산의 결과 값을 chain 형태로 활용할 수 있도록 만들어주는 역할을 한다.

 

 c. 예제 바꿔보기

 public static void main(String[] args) throws ExecutionException, InterruptedException {
     String helloWorldHappy = CompletableFuture.supplyAsync(() -> addWord("", "hello"))
                .thenApply(hello -> addWord(hello, "world"))
                .thenApply(helloWorld -> addWord(helloWorld, "happy"))
                .get();

     System.out.println(helloWorldHappy+" "+Thread.currentThread());
 }

 public static String addWord(String target, String word){
  	System.out.println(word +" 추가 " + Thread.currentThread());
    return target+" "+word;
 }

  -  CompletableFuture 를 이용해 chain 형태로 비동기 연산의 결과를 간단하게 처리 할 수가 있다.

  -  내부동작을 좀 더 살펴보자

   -  .supplyAsync 먼저 살펴보면 내부적으로 CompletableFuture를 생성하고 전달한 lamda 와 함께 AsyncSupply를 생성하여 비동기로 처리한다.

   -  AsyncSupplyCompletableFuture 의 내부에 존재하는 클래스로 Runnable을 구현하고 있어 비동기 실행이 가능하다.

   -  다시 넘어와서 .thenApply를 살펴보면

  -  위의 .supplyAsync 의 결과인 CompletableFuture가 this인 것을 볼 수 있고 .thenApply의 결과는 dependents로 추가되는 것을 볼 수 있다. 

  -   이런 형태로 CompletableFuture 는 비동기 처리 연산을 연결지어 하나의 chain 형태로 처리할 수 있도록 해준다

반응형

블로그의 정보

57개월 BackEnd

BFine

활동하기