


JVM 은 따로 스레드 모델을 규정하진 않는다.
스레드 모델은 플랫폼 독립적으로 구현하려면 1:N 유저 스레드 모델을 사용해야 하는데 이는 1.2 까지 쓰이다 폐기되었다.
대부분은 OS 의 기본 스레드 모델인 1:1을 따른다.
따라서 JVM 은 스레드 스케줄링 등을 관리하지 않고 OS 에 맡긴다.
자바는 기본적으로 선점형 스케줄링을 사용한다.
코틀린 코루틴을 사용하면 JVM 에서도 협력적 스케줄링을 사용할 수 있다.
윈도우의 경우 과거 협력적 스케줄링 방식으로 프로세스 하나가 문제가 생기면 전체가 먹통이 되었다.
현재는 선점형 스케줄링 방식을 사용하므로 작업관리자로 특정 프로세스 하나를 종료할 수 있다.
자바 스레드는 제어권을 가져올 순 없지만, 스레드별로 우선순위를 가지고 시스템에게 권고할 수 있다.
Thread.MIN_PRIORITY(1) ~ Thread.NORM_PRIORITY(5) ~ Thread.MAX_PRIORITY(10)
의 10가지다.
하지만 이는 단순 권고이지 그대로 믿으면 안된다.
특히 자바 스레드 우선순위는 OS 스레드 우선순위와 연결되어야 하는데, 윈도우는 스레드 우선순위가 7가지다.
따라서 자바 스레드 우선순위는 윈도우 스레드 우선순위로 연결되면서 문제가 생긴다.
자바 우선순위 1, 2 는 THREAD_PRIORITY_LOWEST 하나로 연결되어 자바에는 1, 2 로 구분했지만 윈도우에서는 같은 우선순위를 가지는 일이 생긴다. 마찬가지로 3과 4,6과 7, 8과 9가 그렇다.

자바의 스레드는 항상 위 6가지 하나의 상태를 가진다.
Waiting
Timed Waiting
Blocked 와 Waiting
Waiting 은 스레드가 잠들어 누군가가 깨워야 한다.
반면 Blocked 는 락을 얻기 위해 기다리는 상태이며, 락을 얻으면 Running 으로 바뀐다.
자바는 커널 스레드와 자바 스레드를 1:1 맵핑한다.
자바 스레드는 커널 스레드의 자세한 기능을 숨기는 인터페이스를 제공하여 자바 애플리케이션 개발을 쉽게 할 수 있었다.
자바 서블릿은 하나의 커널 스레드에 하나의 Http 요청을 맵핑할 수 있었다.
하지만 컴퓨터가 빨라지고, 요청이 많아지고, MSA 환경에서 IO 가 많아지면서 1:1 모델의 단점인 자원의 한계가 두드러졌다.
짧고 많은 요청은 요청 시간과 컨텍스트 스위칭 시간이 거의 비슷해지는 지경에 이르렀다.
컨텍스트 스위칭 비용이 상대적으로 커졌다.
스레드 전환시 문맥에 대한 저장/복원이 비용이라 한다면, 이를 애플리케이션에서 처리하면 된다.
커널에서 컨텍스트 스위칭을 위한 비용보다 애플리케이션 스택에서 처리하는게 더 빠르고 좋다.
즉, 스레드 스케줄링을 각 코루틴이 하는 것이다.
하지만 코루틴은 협력적 스케줄링 방식으로서 애플리케이션에서 OS 가 하던 기능을 모두 구현하기는 매우 어렵다.
코루틴 <> 협력적 스케줄링 <> 사용자 스레드 <> 가상 스레드 넷은 비슷비슷한 말이다.
스택풀 코루틴 : 코루틴이 각각 스택에 문맥을 위한 저장을 한다.
스택리스 코루틴 : 스택이 없고 상태 머신으로 스레드를 복구한다.
협력적 스케줄링을 사용하는 코루틴이 보통의 개념이다. 하지만 비협력적 스케줄링을 사용하는 코루틴도 있다.

https://waterfogsw.tistory.com/72
Loom 프로젝트로 불리던 Java 가상 스레드는 일종의 코루틴이다.
자바가 복잡한 코루틴을 구현 해 준 것이다.
JDK21 에 정식 반영되었으며, 기존의 Thread 에 추가된 기능이기에 코드 변경이 적다.
가상 스레드의 애플리케이션 레벨 스케줄러는 기본적으로 ForkJoinPool 을 사용한다.