https://seungkyu-han.tistory.com/109
동기, 비동기란 무엇일까?
스프링을 공부하기 전에 항상 나오는 말이 있다. 스프링은 동기, node 서버는 비동기라는 말을 굉장히 많이 들었던 것 같다. 처음에 공부할 때는 외우고만 있다가 해당 내용을 운영체제에서 공부
seungkyu-han.tistory.com
저번에 작성한 동기, 비동기와 연결이 되는 글이다.
앞서 작성했던 프로그램 A와 프로그램 B의 공통점은 둘 다 호출하는 main 함수가 getValue 함수가 시행되는 동안 Blocking 상태가 된다는 것이다.
각각 프로그램이 실행되는 모습을 그려보면 다음과 같다.
모두 메인 함수가 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();
}
}
}
해당 코드에서는 준비가 되기 전까지 계속 메인에서 코드를 실행하게 된다.
그리고 결과를 보면 메인 스레드 외에도 다른 스레드가 실행되는 것을 볼 수 있다.
메인 스레드는 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();
}
}
}
이렇게 메인 스레드는 시작하자마자 종료가 되고, 남은 스레드 혼자 실행이 되고 있는 것을 볼 수가 있다.
'백엔드 > 리액티브 프로그래밍' 카테고리의 다른 글
CompletableFuture를 사용한 성능튜닝 (0) | 2024.03.06 |
---|---|
CompletableFuture 인터페이스 (1) | 2024.03.06 |
CompletionStage 인터페이스 (1) | 2024.03.05 |
Future 인터페이스 (1) | 2024.01.09 |
동기, 비동기란 무엇일까? (0) | 2024.01.08 |