본문 바로가기
일/java

Java Spring Boot Multi Threading

by blair2dev 2022. 1. 11.

 

@Async Annotation을 활용하면 비동기 메소드를 손쉽게 작성할 수 있다. 

@Async 어노테이션이 선언된 메소드는 비동기 메소드로 동작하게 된다. (AOP)

@Async 어노테이션이 선언된 메소드는 리턴 타입에 따라 내부적으로 상이하게 동작한다. 

  • void :
    별도의 쓰레드로 실행되며, 리턴이 없으므로 결과를 기다리지 않고 다음 로직이 수행된다. ThreadPoolTaskExcutor에 의해 자동으로 스레드를 새로 생성해서 비동기 블록 로직을 수행한다.
    logger.info(“start”)
    @Async
    public void t1 (){
          logger.info(“start async logic”)
          Thread.sleep(1000);
          logger.info(“end async logic”)
    }
    logger.info(“non-blocking”)

    [logger]
    >start
    >non-blocking
    >start async logic
    >end async logic

  • Future :
    리턴값을 받아야 한다면 Future 를 이용해야 한다.
    @Async
    public Future<Integer> methodName(String name) throws InterruptedException{
        logger.info(“start async logic”)
       
        return new AsyncResult<>(“return”);
    }

    //caller 쪽에서는 아래와 같이 작성한다.
    Future<Integer> future = instanceName.methodName(“param”)
    logger.(future.get())

    future의 get 메소드는 메소드의 결과를 받을 때까지 계속기다린다.
    메소드가 완료될때까지 기다린다. (블로킹이 발생한다.)
  • ListenableFuture :
    @Async
    public ListenalbleFuture<Integer> methodName(String name) throws InterruptedException{
        logger.info(“start async logic”)
       
        return new AsyncResult<>(“return”);
    }

    //caller
    ListenableFuture<Integer> future = instanceName.methodName(“param”)
    future.addCallback(s -> logger.info(“retuen string is ”) + s);
    logger.info(“non-blocking”)

    [logger]
    >non-blocking
    >start async logic
    >retuen string is return

    future.addcallback  은 비동기 메서드 내부 로직이 완료되면 수행되는 콜백기능이다.
    위 future.get은 리턴을 받을 때까지 기다리지만 (block) callback 을 넣으면
    아래 로직을 타다가 리턴을 받을 때 실행된다.
  • CompletableFuture :
    @Async
    public CompletableFuture<Integer> methodName(String name){
       logger.info(“start method ” + name);
       Thread.sleep(3000);
       logger.info(“end method ” + name);
      
        return new AsyncResult<> (“ returns”).completable()
    }

    get 메서드 사용
    completable 메소드를 사용하면 CompletableFuture 리턴할 있다.

    //caller
    CompletableFuture<Integer> future = instanceName.methodName(“param”);
    logger.info(“non-blocking”);
    logger.info(“blocking : ” + future.get());
    logger.info(“after blocking”);

    [logger]
    >non-blocking
    >start method param
    >end method param
    >blocking : returns
    >after blocking

    Future 마찬가지로 get 메소드 리턴값을 받을 때까지 블로킹이 발생한다.
    Completable method 메인쓰레드가 아닌 별도의 쓰레드로 동작한다.
    메인 쓰레드는 methodName 실행한 잠시동안 논블로킹으로 동작한다.
    따라서 메소드 내부의 로그가 찍히기 전에 non-blocking 로그가 먼저 찍히고
    get 메서드를 실행하게 되는 시점에 다시 블로킹된다.

    callback 메서드 사용
    전체 과정을 non blocking으로 동작하게 하고 싶다면 callback 쓴다.
    CompletableFuture 에서 제공하는 thenAccept 쓰면 된다.

    //caller
    CompletableFuture<Integer> future = instanceName.methodName(“param”);
    logger.info(“11non-blocking”);
    future.thenAccept(p -> logger.info(“callback massege” + p) );
    logger.info(“22non-blocking”);

    [logger]
    >11non-blocking
    >22non-blocking
    >start method param
    >end method param
    >callbackmassege returns

    이는 메인쓰레드는 완벽히 논블로킹으로 작동하고
    thenAccept 별개 스레드로 동작하게 된다.

 

 

REFERANCE : https://brunch.co.kr/@springboot/401

' > java' 카테고리의 다른 글

Java 비동기 서버 Trouble Shooting :: Heap MEM, Thread Pool  (0) 2022.02.21
java 동시성 제어  (0) 2022.02.09