JAVA

가상 쓰레드 (Virtual Threads)

도원좀비 2025. 3. 12. 20:49

1️⃣ 가상 쓰레드란?

  1. Java 19에서 도입되고, Java 21에서 정식 기능으로 추가된 새로운 경량 쓰레드
  2. 기존의 플랫폼 쓰레드보다 훨씬 가볍고, 대량의 동시성을 처리할 수 있다.
  3. OS 쓰레드(플랫폼 쓰레드)를 직접 사용하지 않고, JVM이 관리하는 가벼운 쓰레드

1.가상 쓰레드의 주요 특징

  1. OS 쓰레드와 1:1 매핑되지 않는다 → 기존의 Thread와 다르게 OS 쓰레드를 직접 점유하지 않는다.
  2. 수백만 개의 가상 쓰레드 생성 가능 → OS 리소스를 거의 사용하지 않기 때문에 대량의 동시 작업을 실행할 수 있다.
  3. 논블로킹 I/O와 궁합이 좋다 → 네트워크 요청, DB 쿼리, 파일 입출력 등에서 높은 효율성을 보인다.
  4. 컨텍스트 스위칭 비용이 거의 없 → OS 쓰레드 변경이 필요하지 않기 때문에 성능이 향상.
  5. 기존의 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