함수형 인터페이스는 자바 8부터 도입되었으며, 1개의 추상 메서드를 갖는 인터페이스입니다. 함수형 프로그래밍을 지원하며, 함수를 1급 객체로 사용할 수 있습니다. 예를 들어 Function
, Consumer
, Supplier
, Runnable
등이 있으며, 람다식을 통해 익명 클래스를 간결하게 표현할 수 있습니다.
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
public class LambdaExample {
public static void main(String[] args) {
Calculator addition = (a, b) -> a + b;
Calculator subtraction = (a, b) -> a - b;
System.out.println("Addition: " + addition.calculate(5, 3)); // 출력: 8
System.out.println("Subtraction: " + subtraction.calculate(5, 3)); // 출력: 2
}
}
동기는 Caller가 Callee의 결과에 관심이 있고, 결과를 얻은 후에 특정 액션을 수행하는 것을 의미합니다.
비동기는 Caller가 Callee의 결과에 관심이 없고, Callee는 작업이 완료되면 특정 콜백을 실행합니다.
Blocking은 callee를 호출한 후 callee가 완료되기 전까지 caller가 아무것도 할 수 없는 상태를 말합니다. 제어권은 callee에게 있으며, 추가적인 thread가 필요하지 않습니다.(혹은 추가적인 thread 사용 가능)
Non-Blocking은 callee를 호출한 후 callee가 완료되지 않더라도 caller는 본인의 일을 할 수 있는 상태를 말합니다. 제어권은 caller에게 있으며, caller와 callee는 별도의 thread가 필요합니다.
동기 blocking : caller는 아무 것도 할 수 없는 상태가
된다. 결과를 얻은 후 직접 처리한다
비동기 blocking : caller는 아무 것도 할 수 없는 상태가
된다. 결과는 callee가 처리한다
동기 non blocking : caller는 자기 할 일을 할 수 있다. 결과
를 얻은 후 직접 처리한다
비동기 non blocking : caller는 자기 할 일을 할 수 있다. 결과
는 callee가 처리한다
CPU Bound Blocking은 thread가 대부분의 시간 CPU를 점유하면서 연산이 많은 경우 발생합니다. 추가적인 코어를 투입할 수 있습니다.
IO Bound Blocking은 thread가 대부분의 시간을 대기하면서 파일 읽기/쓰기, 네트워크 요청 등 IO 작업이 많은 경우 발생합니다. Non-Blocking으로 대체할 수 있습니다.
Blocking은 함수 호출이 중첩될 때 전파됩니다. 하나의 함수에서 여러 함수를 호출하고 함수 호출이 중첩되면서 callee는 caller가 되고 다른 callee를 호출할 수 있습니다. 이때, blocking한 함수를 하나라도 호출하면 caller는 blocking 상태가 됩니다. 따라서 Non-Blocking하려면 모든 함수가 Non-Blocking이어야 합니다.
동기 Blocking은 Application이 Kernel에게 I/O 작업을 완료할 때까지 기다리는 상태입니다. 결과를 얻은 후 직접 처리합니다.
가장 흔하게 사용하는 I/O 모델로 user 공간에 존재하는 process는 운영체제 커널에게 I/O를 요청하는 함수를 호출합니다. (system call) 그리고 커널이 작업결과를 반환하기까지 중단된 채 대기(block)합니다. 이때 user process는 CPU를 점유하지 않으며 커널의 응답을 기다립니다.
동기 Non-Blocking은 Application이 Kernel에 주기적으로 I/O 작업이 완료되었는지 확인하고 중간 중간 본인의 일을 할 수 있습니다. 결과를 얻은 후 직접 처리합니다.
block과 다르게 반환할 데이터가 준비되지 않았더라도 기다리지 않고 -1 을 대신 반환합니다. 그리고 왜 반환이 불가능한지에 대한 오류 코드(errno)를 같이 제공합니다. 보통 오류코드로 EAGAIN 또는 EWOULDBLOCK을 반환 받게 됩니다.
user process는 원하는 결과를 반환받을 때까지 계속해서 커널에 상태를 체크해야합니다.
비동기 + Non-Blocking 환경에서는 user process가 커널 I/O system call 이후 처리에 신경쓰지 않고 작업이 완료되면 커널로부터 신호를 받습니다. 결과가 오기 전까지 user process는 I/O를 신경쓰지 않고 다른 작업을 수행할 수 있습니다.
동기 Blocking: Application은 Kernel이 I/O 작업을 완료할 때까지 기다리며 결과를 얻은 후 직접 처리합니다.
비동기 Blocking : x , 따로 다루지 않음
동기 Non-Blocking: Application은 Kernel에 주기적으로 I/O 작업이 완료되었는지 확인하고 결과를 얻은 후 직접 처리합니다.
비동기 Non-Blocking: Application은 Kernel에 I/O 작업 요청을 보내고 본인의 일을 수행합니다. 작업이 완료되면 Kernel은 signal을 보내거나 callback을 호출합니다.
이렇게 동기와 비동기, Blocking과 Non-Blocking의 조합에 따라 다양한 상황을 다룰 수 있습니다.
출처
https://blog.naver.com/n_cloudplatform/222189669084
패스트 캠퍼스 Spring Webflux 완전 정복 : 코루틴부터 리액티브 MSA 프로젝트까지