728x90

https://seungkyu-han.tistory.com/109

 

동기, 비동기란 무엇일까?

스프링을 공부하기 전에 항상 나오는 말이 있다. 스프링은 동기, node 서버는 비동기라는 말을 굉장히 많이 들었던 것 같다. 처음에 공부할 때는 외우고만 있다가 해당 내용을 운영체제에서 공부

seungkyu-han.tistory.com

저번에 작성한 동기, 비동기와 연결이 되는 글이다.

 

앞서 작성했던 프로그램 A와 프로그램 B의 공통점은 둘 다 호출하는 main 함수가 getValue 함수가 시행되는 동안 Blocking 상태가 된다는 것이다.

각각 프로그램이 실행되는 모습을 그려보면 다음과 같다.

프로그램 A
프로그램 B

 

모두 메인 함수가 Blocking 되는 것을 볼 수 있다.

그렇기 때문에 프로그램 A는 동기이면서 Blocking, 프로그램 B는 비동기이면서 Non-blocking 프로그램이다.

 

그럼 과연 이런 모델들만 있을까?

물론 아니다.

다음 프로그램들을 보자.

package org.example;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ProgramC {

    public static void myLog(String string){
        System.out.println(Thread.currentThread() + " -> " +string);
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        myLog("Start main");

        var count = 1;
        Future<Integer> result = getValue();
        while (!result.isDone()){
            myLog("Waiting for result, count: " + count++);
            Thread.sleep(1000);
        }

        var nextValue = result.get() + 1;
        myLog(String.valueOf(nextValue == 1));

        myLog("Finish main");
    }

    public static Future<Integer> getValue(){
        var executor = Executors.newSingleThreadExecutor();
        try{
            return executor.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    myLog("Start getValue");
                    try{
                        Thread.sleep(1000);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }

                    var result = 0;
                    try {
                        return result;
                    }finally {
                        myLog("Finish getResult");
                    }
                }
            });
        }finally {
            executor.shutdown();
        }
    }
}

 

해당 코드에서는 준비가 되기 전까지 계속 메인에서 코드를 실행하게 된다.

 

그리고 결과를 보면 메인 스레드 외에도 다른 스레드가 실행되는 것을 볼 수 있다.

 

프로그램 C

메인 스레드는 getValue 스레드가 동작하는 중간에도 계속 동작하는 것을 볼 수 있다.

 

해당 프로그램은 동기이면서 Non-blocking 프로그램이다.

 

마지막으로 비동기이면서 Non-blocking 프로그램은 다음과 같을 것이다.

caller 스레드는 반환값이 필요가 없기에 바로 종료될 것이며, callee 본인의 일만 본인의 스레드에서 하게 될 것이다.

package org.example;

import java.util.concurrent.Executors;

public class ProgramD {
    public static void myLog(String string){
        System.out.println(Thread.currentThread() + " -> " +string);
    }

    public static void main(String[] args) {
        myLog("Start main");
        getValue(new Function<Integer>() {
            @Override
            public void accept(Integer integer) {
                var nextValue = integer + 1;
                myLog(String.valueOf(nextValue == 1));
            }
        });
        myLog("Finish main");
    }

    public static void getValue(Function<Integer> callback){
        var executor = Executors.newSingleThreadExecutor();
        try{
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    myLog("Start getValue");
                    try{
                        Thread.sleep(1000);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }

                    var value = 0;
                    try{
                        callback.accept(value);
                    }finally {
                        myLog("Finish getResult");
                    }
                }
            });
        }finally {
            executor.shutdown();
        }
    }
}

 

이렇게 메인 스레드는 시작하자마자 종료가 되고, 남은 스레드 혼자 실행이 되고 있는 것을 볼 수가 있다.

+ Recent posts