1️⃣ 가상 쓰레드란?
- Java 19에서 도입되고, Java 21에서 정식 기능으로 추가된 새로운 경량 쓰레드
- 기존의 플랫폼 쓰레드보다 훨씬 가볍고, 대량의 동시성을 처리할 수 있다.
- OS 쓰레드(플랫폼 쓰레드)를 직접 사용하지 않고, JVM이 관리하는 가벼운 쓰레드
1.가상 쓰레드의 주요 특징
- OS 쓰레드와 1:1 매핑되지 않는다 → 기존의 Thread와 다르게 OS 쓰레드를 직접 점유하지 않는다.
- 수백만 개의 가상 쓰레드 생성 가능 → OS 리소스를 거의 사용하지 않기 때문에 대량의 동시 작업을 실행할 수 있다.
- 논블로킹 I/O와 궁합이 좋다 → 네트워크 요청, DB 쿼리, 파일 입출력 등에서 높은 효율성을 보인다.
- 컨텍스트 스위칭 비용이 거의 없 → OS 쓰레드 변경이 필요하지 않기 때문에 성능이 향상.
- 기존의 Thread API와 동일하게 사용 가능 → Thread.ofVirtual()을 사용하면 기존 코드를 쉽게 가상 쓰레드로 변경 가능.
2.가상 쓰레드는 어떻게 동작할까?
✅ 가상 쓰레드는 Carrier Thread(운반자 쓰레드) 위에서 실행
✅ Java의 ForkJoinPool을 이용해서 내부적으로 가상 쓰레드를 OS 쓰레드에 매핑
✅ I/O 작업을 만나면 Carrier Thread에서 분리되어 다른 작업을 실행할 수 있다.
기존 쓰레드 vs 가상 쓰레드의 실행 방식
기존 쓰레드의 동작 방식
- OS 쓰레드가 DB 요청을 실행하면 결과가 올 때까지 블로킹 상태로 대기.
- 쓰레드 개수가 한정되어 있기 때문에 많은 요청을 처리하려면 쓰레드 풀을 크게 늘려야 한다.
가상 쓰레드의 동작 방식
- DB 요청을 실행하면 Carrier Thread에서 가상 쓰레드가 분리
- Carrier Thread는 다른 가상 쓰레드를 실행할 수 있어 리소스를 효율적으로 활용 가능.
✅ 즉, 기존의 쓰레드는 블로킹이 발생하면 쓰레드가 놀지만, 가상 쓰레드는 다른 작업을 처리할 수 있다.
2️⃣ 기존 쓰레드와의 차이점
| 쓰레드 종류 | 실행 방식 | 특징 |
| 플랫폼 쓰레드 (기존 Thread) | OS 쓰레드 1:1 매핑 | 생성 비용 높음, 제한된 개수만 가능 |
| 가상 쓰레드 (VirtualThread) | JVM이 관리 | 매우 가벼움, 수백만 개 생성 가능 |
✅ 즉, 가상 쓰레드는 기존 쓰레드보다 훨씬 가볍고 동시성 성능이 뛰어나다
3️⃣ 가상 쓰레드 사용법
기본적인 가상 쓰레드 실행 (Thread.ofVirtual())
public class VirtualThreadExample {
public static void main(String[] args) {
Thread vThread = Thread.ofVirtual().start(() -> {
System.out.println("가상 쓰레드 실행: " + Thread.currentThread());
});
try {
vThread.join(); // 가상 쓰레드가 끝날 때까지 대기
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Executor를 사용한 가상 쓰레드 풀
기존 FixedThreadPool을 사용하는 것처럼 가상 쓰레드도 ExecutorService를 활용할 수 있다.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class VirtualThreadExecutorExample {
public static void main(String[] args) {
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10; i++) {
int taskNumber = i;
executor.submit(() -> {
System.out.println("작업 " + taskNumber + " 실행: " + Thread.currentThread());
});
}
}
}
}
✅ 수백만 개의 가상 쓰레드를 생성할 수 있
4️⃣ 가상 쓰레드 vs 기존 쓰레드 비교
기존 ThreadPool을 사용할 때의 문제점
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TraditionalThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10); // 고정된 쓰레드 개수
for (int i = 0; i < 100; i++) { // 100개의 작업 실행
int taskNumber = i;
executor.submit(() -> {
System.out.println("작업 " + taskNumber + " 실행: " + Thread.currentThread());
});
}
executor.shutdown();
}
}
❌ 쓰레드 개수가 제한되므로, 동시성이 높은 작업에서는 효율이 떨어진다
가상 쓰레드를 사용하면? (Executors.newVirtualThreadPerTaskExecutor())
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class VirtualThreadPerformanceExample {
public static void main(String[] args) {
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 100; i++) {
int taskNumber = i;
executor.submit(() -> {
System.out.println("작업 " + taskNumber + " 실행: " + Thread.currentThread());
});
}
}
}
}
✅ 가상 쓰레드는 개수 제한 없이 동시성을 극대화할 수 있다.
5️⃣ 가상 쓰레드가 유용한 경우
✅ I/O 바운드 애플리케이션 (웹 서버, API 서버, 데이터베이스 요청 등)
✅ 대량의 동시 요청을 처리해야 하는 경우 (채팅 서버, 메시징 시스템)
✅ 파일 다운로드, 업로드 등 네트워크 작업
❌ 가상 쓰레드가 적합하지 않은 경우
🚫 CPU 바운드 작업 (복잡한 계산, 머신러닝, 이미지 처리 등)
🚫 ThreadLocal을 많이 사용하는 경우
가상 쓰레드 vs 기존 쓰레드
| 비교 항목 | 기존 Thread | VirtualThread |
| 쓰레드 개수 제한 | OS 리소스에 의해 제한 | 제한 없음 (수백만 개 가능) |
| 컨텍스트 스위칭 비용 | 높음 (커널 모드 전환 필요) | 낮음 (유저 모드에서 실행) |
| I/O 바운드 작업 | 비효율적 | 효율적 |
| CPU 바운드 작업 | 적합 | 적합하지 않음 |
✅ 결론적으로, 가상 쓰레드는 I/O 중심의 동시성 작업에 강력한 성능을 제공
'JAVA' 카테고리의 다른 글
| Java Map(맵) (2) | 2025.03.12 |
|---|---|
| CompletableFuture (비동기 처리) (1) | 2025.03.12 |
| Executor 프레임워크 (0) | 2025.03.12 |
| 쓰레드 동기화 (Synchronization) (3) | 2025.03.11 |
| 쓰레드(Thread) (0) | 2025.03.11 |