Summary
높은 처치량의 동시성 애플리케이션을 개발하는데 사용하는 lighweight threads.
History
JDK 19 미리보기 기능으로 제안되었고, 아래 변경사항을 포함하여 JDK 21에 추가될 예정
- thread-local variables 지원
- Thread API를 통해 직접 생성 가능
Goals
- thread-per-reqeust style로 하드웨어를 최대한 활용한 코드를 쉽게 작성 할 수 있게 해준다.
- java.lang.Thread API를 사용하여 최소한의 변경으로 가상 스레드를 적용할 수 있게 한다.
- 기존 JDK 툴로 트러블 슈팅, 디버깅, 프로파일링을 가능하게 한다.
Non-Goals
- 전통적인 스레드 구현을 제거하거나, 가상 스레드 사용으 위해서 기존 애플리케이션을 마이그레이션하는 것이 목표가 아님.
- java 기본 동시성 모델을 변경하는것이 목표가 아님
- java 언어나 라이브러리에서 새로운 데이터 병령 처리 구성을 제공하는 것이 목표가 아님, Stream API는 대용량 데이터를 병렬로 처리하는 방법으로 남아 있음.
Motivation
The tread-per-request style
서버 애플리케이션은 사용자 요청을 처리할 때 사용자 요청에 전용 스레드를 할당하여 처리한다. thread-per-request style은 개발 및 디버깅이 쉽다. 그러나 JDK는 스레드를 운영체제(OS) 스레드 레퍼로 구현하기 때문에 사용 가능한 스레드의 수가 제한된다.
OS 스레드는 비싼 비용의 리소스고, OS 스레드를 많이 사용하는 경우 CPU 또는 네트워크 연결과 같은 다른 리소스가 소진되기 전에 스레드 수가 제한 요소가 되는 경우가 많다.
Improving scalability with the asynchronous style
하드웨어를 최대한 활용하려는 일부 개발자는 thread-sharing 스타일을 더 선호하여 thread-per-request 스타일을 포기했다.
요청 처리 코드는 하나의 스레드가 전부 처리하지 않고, 스레드가 다른 요청을 처리할 수 있도록 다른 I/O 작업이 완료될 때까지 기다리는 동안 해당 스레드는 스레드 풀로 반환한다.
스레드 공류를 통해 많은 수의 스레드를 소비하지 않고 많은 수의 동시 작업을 수행할 수 있다. OS 스레드 부족으로 인한 처리량 제한은 사라졌지만, 비용이 많이 든다.(it comes at a high price)
비동기식 스타일에서는 요청의 각 단계가 다른 스레드에서 실행될 수 있고, 모든 스레드는 인터리브 방식으로 서로 다른 요청에 속하는 단계를 실행한다. 프로그램 동작을 이래하기 어렵고, 스택 추적, 디버일이 어렵고 애플리케이션의 동시성 단위가 더이상 플랫폼의 동시성 단위가 아니기 때문에 java 플랫폼과 맞지 않다.
Preservinf thr thread-per-request style with cirtual threds
플랫폼과의 조화를 유지하고 애플리케이션을 확장할 수 있도록 하려면 thread-per-request 스타일을 유지하도록 노력해야한다.
운영체제는 OS 스레드를 더 효율적으로 구현할 수 없지만 java에서는 OS 스레드에 대한 일대일 대응을 분리하는 방식으로 java 스레드를 구현한는 것이 가능하다. 가상 스레드는 특정 java.lang.ThreadOS 스레드에 연결되지 않는 인스턴스고, 이와 대조적으로 플랫폼 스레드는 java.lang.Thread OS 스레드를 wrapper 하는 전통적인 방식을 구현한 인스턴스다.
thread-per-reqest 스타일에 애플리케이션 코드는 전체 요청 기간 동안 가상 스레드에서 실행되지만, 가상 스레드는 CPU에서 계산을 수행하는 동안에만 OS 스레드를 사용한다.(비동기 방식과 확장성이 동일)
Implications of virtual threads
가상 스레드는 cheep and plentiful 하여 불링하지 않아야한다. 모든 애플리케이션 작업에 대하여 새로운 가상 스레드를 생성해야한다. 대부분의 가상 스레드는 수명이 짧고 얕은 호출 스택을 가지며 단일 HTTP 호출이나 JDBC 쿼리만 수행한다.
가승 스레드는 사용 가능한 하드뤠어를 최적으로 활용하면서 java 플랫폼의 디자인과 조화를 이루는 안정적인 thread-per-request 스타일을 유지한다. 아래와 같은 경우 애플리케이션 처리량을 크게 향상 시킬 수 있다.
- The number fo concurrent tasks is high(more than a few thousand), and
- The workload is not CPU-bound, since havnig many more threads than processort cores cannot improve throughput in that case.
(Ex gorutines in Go and process in Erlang)
Spring Boot 3.2.0
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.2.0-M1-Release-Notes
Thread vs Virtual Thread
@RestController
@RequestMapping("/load")
public class LoadTestController {
private static final Logger LOG = LoggerFactory.getLogger(LoadTestController.class);
@GetMapping
public void doSomthing() throws InterruptedException {
LOG.info("hey, I'm doing something");
Thread.Sleep(1000);
}
}
Thread | Virtual Thread |
참고
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.2.0-M1-Release-Notes
'dev > java' 카테고리의 다른 글
Generational ZGC in Java 21 (0) | 2024.07.02 |
---|---|
Java Virtual Threads 사용 시 synchronized 주의 (0) | 2024.06.04 |
java rsa 기반의 암호화 (0) | 2016.01.04 |
자바 메모리 구조 (0) | 2010.08.26 |
Writing the MINA time server (0) | 2007.04.17 |