개발자는 기록이 답이다

패스트캠퍼스 환급챌린지 6일차 미션 (2월 6일) : Spring Webflux 완전 정복 : 코루틴부터 리액티브 MSA 프로젝트까지 강의 후기 본문

패스트캠퍼스

패스트캠퍼스 환급챌린지 6일차 미션 (2월 6일) : Spring Webflux 완전 정복 : 코루틴부터 리액티브 MSA 프로젝트까지 강의 후기

slow-walker 2024. 2. 6. 22:54

 

 

1. CompletableFuture 

public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {...}
    public static CompletableFuture<Void> runAsync(Runnable runnable) {...}
    
    public boolean complete(T value) {...}
    public boolean isCompletedExceptionally() {...}
    
    public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {...}
    public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {...}
}

 

 

2. CompletableFuture 의 연산자 - supplyAsync

 

  • Supplier를 제공하여 CompletableFuture를 생성 가능
  • Supplier의 반환값이 CompletableFuture의 결과로

함수형 인터페이스인 Supplier로 부터 힌트를 얻을 수 있는데, 인자로 supplier를 받게 된다.

Supplier는 아무런 인자도 받지 않고 값을 내리는 함수형 인터페이스 이다.

이런 Supplier의 성격을 생각해보면 supplyAsync는 아무런 값이 없는 상태에서 값을 최초로 만들어서 내려주는 기능을 하는 메소드라는걸 알 수 있다. 즉, Supplier를 실행해서 내려주는 결과(반환값)를 CompletableFuture로 반환하게 된다.

 

3. CompletableFuture 의 연산자 - runAsync

  • Runnable를 제공하여 CompletableFuture를 생성할 수 있다
  • 값을 반환하지 않는다
  • 다음 task에 null이 전달된다.

 

Runnable은 받는 값도 없고, 내려주는 값도 없다. 따라서 CompletableFuture를 생성하긴 하는데, 구체적인 값을 내리는게 아니라, 정확히는 Runnable에 주어진 액션이 종료가 됬으면 chaining을 해서 작업을 처리할래? 라는 사건을 전달한다.

 

4. supplyAsync 와 runAsync의 구체적인 예시

 

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Slf4j
public class CompletableFutureSupplyAsyncExample {
    public static void main(String[] args)
            throws ExecutionException, InterruptedException {
        log.info("start main");
        var future = CompletableFuture.supplyAsync(() -> {
            log.info("supplyAsync");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return 1;
        });
        assert !future.isDone();

        Thread.sleep(1000);

        assert future.isDone();
        assert future.get() == 1;

        log.info("end main");
    }
}

 

  1. supplyAsync를 만들고 Thread.sleep을 100 동안함
  2. 그 이후 1 반환
  3. future를 생성하고 나서 상태를 봤을때 isDone이 아닐 것이다.
  4. supplyAsync는 논블로킹으로 동작하기 때문에 확인하는 시점에는 false가 나올 것이다.
  5. 그 이후 다시 Thread.sleep을 1초 하고 시간이 지나면서 다시 확인하면 true가 나올 것이다.
  6. 값도 1로 조회할 수 있다.
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Slf4j
public class CompletableFutureRunAsyncExample {
    public static void main(String[] args)
            throws ExecutionException, InterruptedException {
        log.info("start main");
        var future = CompletableFuture.runAsync(() -> {
            log.info("runAsync");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        assert !future.isDone();

        Thread.sleep(1000);
        assert future.isDone();
        assert future.get() == null;

        log.info("end main");
    }
}
  1. runAsync는 아무런 값을 반환하지 않는다
  2. Thread.sleep 100만 한다
  3. 첫번째 ISDone에서 100을 지나지 않았을때라서 False이다
  4. Thread.sleep 을 1초동안 하고나서 접근한다
  5. 다 지나면서 완료가 되고 두번째 ISDone이 true이다
  6. 결과값은 null이 나온다.

 

 

※ 본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다. https://bit.ly/48sS29N