Java Academy · 강의

플랫폼 스레드와 가상 스레드

각각 적절한 사용 시점을 알아봅니다

레슨 3/413개 단계

플랫폼 스레드와 가상 스레드은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

두 종류의 스레드

이제 Java에는 두 종류의 스레드가 있습니다. 플랫폼 스레드는 OS 스레드를 감싸는 전통적인 스레드입니다. 가상 스레드는 가볍고 JVM이 관리합니다.

각각을 언제 사용해야 하는지 아는 것이 확장 가능한 동시성 Java 프로그램을 작성하는 핵심입니다.

플랫폼 스레드 생성하기

Thread.ofVirtual()에 대응하는 Thread.ofPlatform()을 사용하면 플랫폼 스레드를 생성할 수 있습니다.

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread p = Thread.ofPlatform().name("native-worker").start(() ->
            System.out.println("Platform? " + !Thread.currentThread().isVirtual()));
        p.join();
    }
}

비용 비교

플랫폼 스레드는 무겁습니다.

  • 각 스레드마다 약 1 MB의 스택을 예약합니다
  • 생성 속도가 느립니다
  • 몇 천 개로 제한됩니다

가상 스레드는 저렴합니다. 초기 스택이 작고 생성이 빠르며 수백만 개도 가능합니다.

입출력 중심 작업

작업이 네트워크, 디스크 또는 데이터베이스를 기다리는 데 대부분의 시간을 쓴다면 가상 스레드가 훨씬 유리합니다.

가상 스레드 하나가 블로킹되는 동안 해당 캐리어 스레드는 다른 작업을 실행할 수 있도록 해제되므로, 소수의 OS 스레드로 수천 개의 요청을 처리할 수 있습니다.

CPU 작업 중심 작업

블로킹되지 않는 순수 계산 작업에서는 가상 스레드가 속도를 높여 주지 않습니다. 처리량은 코어 수에 제한됩니다.

이 경우 프로세서 수에 맞춘 고정 풀이 적절한 도구입니다.

import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws Exception {
        int cores = Runtime.getRuntime().availableProcessors();
        try (ExecutorService cpu = Executors.newFixedThreadPool(cores)) {
            Future<Long> f = cpu.submit(() -> {
                long s = 0;
                for (long i = 0; i < 1_000_000L; i++) s += i;
                return s;
            });
            System.out.println("Cores: " + cores + ", sum: " + f.get());
        }
    }
}

블로킹 동작 시뮬레이션

이 코드 조각은 많은 가상 스레드가 동시에 대기하는 모습을 보여 줍니다. 여기서 대기는 블로킹 입출력을 대신합니다. 같은 작업을 플랫폼 스레드 10,000개로 수행하는 상황을 상상해 보세요.

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
    public static void main(String[] args) {
        AtomicInteger done = new AtomicInteger();
        try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
            for (int i = 0; i < 10_000; i++) {
                exec.submit(() -> {
                    try { Thread.sleep(50); } catch (InterruptedException e) {}
                    done.incrementAndGet();
                });
            }
        }
        System.out.println("Finished blocking tasks: " + done.get());
    }
}

데몬 상태

가상 스레드는 항상 데몬 스레드이며 비데몬 스레드로 변경할 수 없습니다. 플랫폼 스레드는 기본적으로 생성자의 데몬 상태를 상속하지만 명시적으로 설정할 수 있습니다.

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread v = Thread.ofVirtual().unstarted(() -> {});
        Thread p = Thread.ofPlatform().unstarted(() -> {});
        System.out.println("virtual daemon: " + v.isDaemon());
        System.out.println("platform daemon: " + p.isDaemon());
    }
}

우선순위 무시

가상 스레드는 항상 NORM_PRIORITY 우선순위를 보고하며 우선순위를 설정해도 효과가 없습니다. 스케줄링은 OS 스케줄러가 아니라 JVM이 처리합니다.

public class Main {
    public static void main(String[] args) {
        Thread v = Thread.ofVirtual().unstarted(() -> {});
        v.setPriority(Thread.MAX_PRIORITY);
        System.out.println("Priority is still: " + v.getPriority());
    }
}

선택 지침

실용적인 경험칙은 다음과 같습니다.

  • 입출력을 기다리는 작업이 많다면 가상 스레드를 사용하세요.
  • CPU에 의해 제한되는 계산 작업이 무겁다면 플랫폼 스레드 고정 풀을 사용하세요.
  • OS 수준의 스레드 조정이 필요하다면(우선순위, 프로세서 선호도) 플랫폼 스레드를 사용하세요.

함께 사용할 수 있습니다

프로그램 전체에서 하나만 선택할 필요는 없습니다. 일반적인 애플리케이션은 요청 처리에 가상 스레드를 사용하고, CPU 집약적인 구간에는 작은 플랫폼 스레드 풀을 사용합니다.

두 종류 모두 동일한 Thread 인터페이스를 공유하므로 함께 사용해도 자연스럽게 동작합니다.

마이그레이션 팁

입출력 중심 서비스로 전환할 때 가장 작은 변경은 실행기를 교체하는 것입니다. 고정 풀이나 캐시 풀을 newVirtualThreadPerTaskExecutor()로 바꾸세요.

다음 레슨에서 다룰 고정 문제와 ThreadLocal의 과도한 사용에는 주의해야 합니다.

빠른 확인

가상 스레드가 가장 뚜렷한 이점을 제공하는 작업을 선택하세요.

정리

두 스레드 모델을 비교해 보았습니다.

  • 플랫폼 스레드: 무겁고 OS 기반이며 CPU 작업 중심 작업과 OS 조정에 적합합니다
  • 가상 스레드: 저렴하고 JVM이 관리하며 항상 데몬이고 입출력 중심 동시성에 적합합니다
  • 두 종류는 함께 사용할 수 있고 동일한 인터페이스를 공유합니다

다음에는 고정 문제와 ThreadLocals의 위험 요소를 배웁니다.

무료로 시작

AI 튜터와 함께 Java을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
104
레슨
374

자주 묻는 질문

“플랫폼 스레드와 가상 스레드” 강의는 무료인가요?

네 — “플랫폼 스레드와 가상 스레드” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“플랫폼 스레드와 가상 스레드”에서 뭘 배우나요?

각각 적절한 사용 시점을 알아봅니다 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“플랫폼 스레드와 가상 스레드” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 가상 스레드란 무엇인가
  2. 가상 스레드 생성
  3. 플랫폼 스레드와 가상 스레드
  4. 함정: 고정과 ThreadLocals
← Java Academy(으)로 돌아가기