3 Sep 2020

[Java] 비동기(Async), non-blocking 동작을 Callback을 통해 구현

Callback을 통해 비동기를 구현해보자


Callback

피호출자(Caller)가 호출자(Callee)를 다시 호출하는 것

비동기(Asynchronous)적 처리를 하기 위한 디자인 패턴의 종류


Callback패턴을 이용한 비동기 방식

A,B클래스가 있을때 A는 B를 실행시키기만 하고 A는 자신의 작업을 지속한다.

B는 작업이 완료되면 A에게 알려준다.

A가 호출한 B가 필요시 다시 A의 메소드를 호출하기 때문에 Callback이라 부른다.


비동기를 통해 실행되는 곳은 새로운 Thread를 이용해 작동시켜야 한다. 그렇지 않으면 Main Thread가 blocking되어 비동기를 구현하는 의미가 없어진다.

예시


콜백 으로 사용할 메소드 인터페이스로 선언

public interface Loader {
   public void onProgressUpdate(String progress);
   public void onComplete(String url);
}


caller

public class FileLoader implements Loader {
    @Override
    public void onProgressUpdate(String progress) {
        System.out.println(progress);
    }

    @Override
    public void onComplete(String url) {
        System.out.println(url);
    }
}


callee version1 (main thread가 blocking 되는 방식)

public class VideoDownLoader{
    private Loader fileLoader;

    public VideoDownLoader(Loader fileLoader){
        this.fileLoader=fileLoader;
    }

    public void execute(){
        System.out.println("다운로드 시작");
        try{
            for(int i=1;i<=10;i++){
                fileLoader.onProgressUpdate("진행중... "+i*10+"%");
                Thread.sleep(1000);
            }
            fileLoader.onComplete("다운로드 완료!");
        }catch (Exception e){}
    }
}


callee version2 (non-blocking 방식으로 구동되는 방식)

public class VideoDownLoader{
    private Loader fileLoader;

    public VideoDownLoader(Loader fileLoader){
        this.fileLoader=fileLoader;
    }

    public void execute(){
         new Thread(()->{
            try{
                for(int i=1;i<=10;i++){
                    fileLoader.onProgressUpdate("진행중... "+i*10+"%");
                    Thread.sleep(1000);
                }
                fileLoader.onComplete("다운로드 완료!");
            }catch (Exception e){}
        }).start();
    }
}


main

public class Main {
    public static void main(String[] args){
        VideoDownLoader videoDownLoader=new VideoDownLoader(new FileLoader());
        videoDownLoader.execute();
        System.out.println("=============================");
        System.out.println(Thread.currentThread().getName());
        System.out.println("=============================");
    }
}


version1 Asynchronous + blocking 실행결과

다운로드 시작
진행중... 10%
진행중... 20%
진행중... 30%
진행중... 40%
진행중... 50%
진행중... 60%
진행중... 70%
진행중... 80%
진행중... 90%
진행중... 100%
다운로드 완료!
=============================
main
=============================

다운로드가 완료 되고 나서야 Main Thread가 진행되는 것으로 추측할 수 있듯이

videoDownLoader.execute(); 호출후 Main Thread가 blocking걸리는 것을 볼 수 있다.


version2 Asynchronous + non-blocking 실행결과

다운로드 시작
=============================
main
=============================
진행중... 10%
진행중... 20%
진행중... 30%
진행중... 40%
진행중... 50%
진행중... 60%
진행중... 70%
진행중... 80%
진행중... 90%
진행중... 100%
다운로드 완료!

다운로드의 진행과 Main Thread가 각기 따로 실행되는 것을 알 수 있따.


Tags:
0 comments