반응형
728x90
반응형
Caller와 Callee
함수가 다른 함수를 호출하는 상황
- Caller : 호출하는 함수
- Callee : 호출 당하는 함수
함수형 인터페이스
함수형 인터페이스는 호출한 쓰레드에서 실행된다.
@Slf4j
public class p030_FunctionalInterfaceExample {
public static void main(String[] args) {
var consumer = getConsumer();
consumer.accept(1);
var consumerAsLambda = getConsumerAsLambda();
consumerAsLambda.accept(1);
handleConsumer(consumer);
}
public static Consumer<Integer> getConsumer() {
Consumer<Integer> returnValue = new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
log.info("value in interface: {}", integer);
}
};
return returnValue;
}
public static Consumer<Integer> getConsumerAsLambda() {
return integer -> log.info("value in lambda: {}", integer);
}
public static void handleConsumer(Consumer<Integer> consumer) {
log.info("handleConsumer");
consumer.accept(1);
}
}
1) 함수형 인터페이스의 메서드 호출
위 호출을 main 메서드에서 했으므로, main 메서드에서 함수형 인터페이스의 메서드가 수행된다.
consumer.accept(1)
실행결과
05:33:36.132 [main] INFO com.example03.asyncprogramming.p030_FunctionalInterfaceExample - value in interface: 1
05:33:36.134 [main] INFO com.example03.asyncprogramming.p030_FunctionalInterfaceExample - value in lambda: 1
05:33:36.134 [main] INFO com.example03.asyncprogramming.p030_FunctionalInterfaceExample - handleConsumer
05:33:36.134 [main] INFO com.example03.asyncprogramming.p030_FunctionalInterfaceExample - value in interface: 1
동기 & 블로킹
@Slf4j
public class p031_SyncBlockingExample {
public static void main(String[] args) {
log.info("Start main");
var result = getResult();
var nextValue = result + 1;
assert nextValue == 1;
log.info("Finish main");
}
public static int getResult() {
log.info("Start getResult");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
var result = 0;
try {
return result;
} finally {
log.info("Finish getResult");
}
}
}
실행결과
실행 결과를 보면, 1초 대기 후 이후 로직이 실행됨을 알 수 있다.
05:37:06.903 [main] INFO com.example03.asyncprogramming.p031_SyncBlockingExample - Start main
05:37:06.905 [main] INFO com.example03.asyncprogramming.p031_SyncBlockingExample - Start getResult
05:37:07.920 [main] INFO com.example03.asyncprogramming.p031_SyncBlockingExample - Finish getResult
05:37:07.921 [main] INFO com.example03.asyncprogramming.p031_SyncBlockingExample - Finish main
- main는 getResult의 결과에 관심이 있다. (동기)
- main은 결과를 이용해서 다음 코드를 실행한다.
- main은 getResult가 결과를 돌려주기 전까지 아무것도 할 수 없다. (블로킹)
- main은 getResult가 완료될때까지 대기한다. (블로킹)
- getResult를 호출한 후, getResult가 완료되지 않으면 main은 본인의 일을 할 수가 없다.
비동기 & 블로킹
@Slf4j
public class p032_AsyncBlockingExample {
public static void main(String[] args) {
log.info("Start main");
// main은 getResult의 결과에 관심이 없다.
// getResult 결과를 이용해서 함수형 인터페이스를 실행한다.
getResult(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
var nextValue = integer + 1;
assert nextValue == 1;
}
});
log.info("Finish main");
}
// ac
public static void getResult(
Consumer<Integer> callback
) {
log.info("Start getResult");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
var result = 0;
try {
callback.accept(result);
} finally {
log.info("Finish getResult");
}
}
}
실행결과
05:38:13.975 [main] INFO com.example03.asyncprogramming.p032_AsyncBlockingExample - Start main
05:38:13.977 [main] INFO com.example03.asyncprogramming.p032_AsyncBlockingExample - Start getResult
05:38:15.000 [main] INFO com.example03.asyncprogramming.p032_AsyncBlockingExample - Finish getResult
05:38:15.000 [main] INFO com.example03.asyncprogramming.p032_AsyncBlockingExample - Finish main
- main은 getResult의 결과에 관심이 없다. (비동기)
- getResult는 결과를 이용해서 함수형 인터페이스를 실행한다.
- main은 getResult가 결과를 구하고 callback을 실행하기 전까지 아무것도 할 수 없다. (블로킹)
- main은 getResult가 완료될때까지 대기한다. (블로킹)
동기 vs 비동기
동기 | 비동기 |
caller는 callee의 결과에 관심이 있다. | caller는 callee의 결과에 관심이 없다. |
caller는 결과를 이용해서 action을 수행한다. | callee는 결과를 이용해서 callback을 수행한다. |
Blocking
- callee를 호출한 후, callee가 완료되기 전까지 caller가 아무것도 할 수 없다.
- 제어권을 callee가 가지고있다.
- caller와 다른 별도의 thread가 필요하지 않다. 혹은 thread를 추가로 쓸 수도 있다.
Non-Blocking
- callee를 호출한 후, callee가 완료되지 않더라도 caller는 본인의 일을 할 수 있다.
- 제어권을 caller가 가지고있다.
- caller와 다른 별도의 thread가 필요하다.
동기 & 논블로킹
@Slf4j
public class p043_SyncNonBlockingExampleRunner {
public static void main(String[] args)
throws InterruptedException, ExecutionException {
log.info("Start main");
var count = 1;
Future<Integer> result = getResult();
while (!result.isDone()) {
log.info("Waiting for result, count: {}", count++);
Thread.sleep(100);
}
var nextValue = result.get() + 1;
assert nextValue == 1;
log.info("Finish main");
}
public static Future<Integer> getResult() {
var executor = Executors.newSingleThreadExecutor();
try {
return executor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
log.info("Start getResult");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
var result = 0;
try {
return result;
} finally {
log.info("Finish getResult");
}
}
});
} finally {
executor.shutdown();
}
}
}
실행결과
05:53:33.806 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Start main
05:53:33.810 [pool-1-thread-1] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Start getResult
05:53:33.810 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Waiting for result, count: 1
05:53:33.928 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Waiting for result, count: 2
05:53:34.104 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Waiting for result, count: 3
05:53:34.277 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Waiting for result, count: 4
05:53:34.452 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Waiting for result, count: 5
05:53:34.627 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Waiting for result, count: 6
05:53:34.800 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Waiting for result, count: 7
05:53:34.886 [pool-1-thread-1] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Finish getResult
05:53:34.967 [main] INFO com.example03.asyncprogramming.p043_SyncNonBlockingExampleRunner - Finish main
- main는 getResult의 결과에 관심이 있다. (동기)
- getResult를 호출한 후, getResult가 완료되지 않더라도 main은 본인의 일을 할 수 있다. (논블로킹)
비동기 & 논블로킹
@Slf4j
public class p048_AsyncNonBlockingExample {
public static void main(String[] args) {
log.info("Start main");
getResult(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
var nextValue = integer + 1;
assert nextValue == 1;
}
});
log.info("Finish main");
}
public static void getResult(Consumer<Integer> callback) {
var executor = Executors.newSingleThreadExecutor();
try {
executor.submit(new Runnable() {
@Override
public void run() {
log.info("Start getResult");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
var result = 0;
try {
callback.accept(result);
} finally {
log.info("Finish getResult");
}
}
});
} finally {
executor.shutdown();
}
}
}
실행결과
05:57:58.623 [main] INFO com.example03.asyncprogramming.p048_AsyncNonBlockingExample - Start main
05:57:58.627 [main] INFO com.example03.asyncprogramming.p048_AsyncNonBlockingExample - Finish main
05:57:58.627 [pool-1-thread-1] INFO com.example03.asyncprogramming.p048_AsyncNonBlockingExample - Start getResult
05:57:59.680 [pool-1-thread-1] INFO com.example03.asyncprogramming.p048_AsyncNonBlockingExample - Finish getResult
- main은 getResult의 결과에 관심이 없다. (비동기)
- getResult를 호출한 후, getResult가 완료되지 않더라도 main은 본인의 일을 할 수 있다. (논블로킹)
동기 & 블로킹
비동기 & 블로킹
동기 & 논블로킹
비동기 & 논블로킹
함수 호출 모델
동기 | 비동기 | |
Blocking | caller는 아무것도 할 수 없는 상태가 된다. 결과를 얻은 후 직접 처리한다. |
caller는 아무것도 할 수 없는 상태가 된다. 결과는 callee가 처리한다. |
Non-Blocking | caller는 자기 할일을 할 수 있다. 결과를 얻은 후 직접 처리한다. |
caller는 자기 할일을 할 수 있다. 결과는 callee가 처리한다. |
'Spring Webflux 완전 정복 : 코루틴부터 리액티브 MSA 프로젝트까지' 강의 참고
반응형
'Coding > Etc' 카테고리의 다른 글
BaekjoonHub - Github 연동하기 (0) | 2022.05.28 |
---|---|
hexo 블로그 시작하기 (테마 next 적용) (0) | 2020.12.18 |
Git Branch 관리 명령어 (조회,생성,삭제,수정) (0) | 2018.10.09 |