이 자료는 javaSE jdk22 의 자료를 해석하고 테스트한 내용입니다.
원본 : https://docs.oracle.com/en/java/javase/22/core/virtual-threads.html#GUID-2BCFC2DD-7D84-4B0C-9222-97F9C7C6C521 (2024.04발행)
JAVA SE 22 API 레퍼런스 : https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Thread.Builder.OfVirtual.html
플랫폼 스레드는 OS 가 스케줄링을 하고 가상 스레드는 자바 런타임이 관리한다.
(1) 자바 런타임이 플랫폼 스레드 상 가상 플랫폼을 할당하거나 마운트한다.
(2) 그리고 나서 OS가 해당 플랫폼 스레드를 스케줄링한다. (이때 플랫폼 스레드를 carrier라고 부름)
(3) 일정 코드를 진행하는 가상스레드는 다시 carrier로부터 언마운트 된다. (보통 IO blocking 때 많이 발생)
(4) 그럼 언마운트 상태인 carrier는 또 다른 가상 스레드를 자바 런타임에 의해 마운트 되어 쓸 수 있게 된다.
carrier(가상스레드가 할당된 플랫폼스레드) 가 pin처리되어 있다면 블로킹 작업 동안에도 가상 스레드가 언마운트 되지 않는다.
(1) 가상스레드가 synchronized 블록 및 메서드에서 실행되고 있을 때
(2) 가상스레드가 native 메서드나 외부 메서드를 실행할 때
위 경우에는 블로킹 작업이 있어도 언마운트 및 다른 가상 스레드에 할당이 아니라 계속 특정 플랫폼 스레드와 연결(마운트) 되어 있는 것이다.
이 경우 가상 스레드의 성능 및 확장성에 영향을 미칠 수 있다.
(1) synchronized 블록 및 메서드가 자주 실행되지 않게 코드를 개선하거나 설계를 변경한다.
(2) 잠재적으로 긴 I/O 작업을 ReentrantLock과 같은 잠금(lock) 메커니즘으로 보호한다.
가상스레드도 기존 스레드처럼 디버깅을 할 수 있다.
JDK Flight Recorder 나 jcmd 툴을 이용해 본인의 앱상에서 가상 스레드를 관찰할 수 있다.
위와 같은 이벤트를 출력하기 위해 아래 명령어를 실행한다.
jfr print --events //jfk 툴로 이벤트를 출력하겠다.
jdk.VirtualThreadStart,jdk.VirtualThreadEnd,jdk.VirtualThreadPinned,jdk.VirtualThreadSubmitFailed recording.jfr
//출력할 대상은 ..Start , ..End , ..Pinned , ..Failed 이며 recording.jfr 에 기록된다.
jcmd <PID> Thread.dump_to_file -format=text <file>
jcmd <PID> Thread.dump_to_file -format=json <file>
위 명령어를 통해 생성된 스레드 덤프에는 IO 블로킹된 가상 스레드와 ExecutorService 인터페이스로 생성된 가상 스레드 등 "특정 유형의 가상 스레드" 에 대한 정보가 포함된다.
단, 객체 주소 , 잠금 , JNI 통계 , 힙 통계 등의 다른 정보등은 포함하지 않는다.
(전통적인 스레드 덤프는 위 정보도 보여주는데 반해 jcmd는 정보가 제한적이다.)