Java 21 새 기능 - Virtual Threads와 Pattern Matching



Java 21 LTS에 추가된 주요 기능들로, 동시성 프로그래밍과 패턴 매칭이 크게 개선되었습니다.



Virtual Threads (가상 스레드)


수백만 개의 경량 스레드를 생성할 수 있어 I/O 바운드 작업에 최적화됩니다.



// 가상 스레드 생성
Thread vThread = Thread.ofVirtual().start(() -> {
System.out.println("Virtual Thread: " + Thread.currentThread());
});

// ExecutorService with Virtual Threads
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}

// Spring Boot에서 활용
// application.yml
spring:
threads:
virtual:
enabled: true


Pattern Matching for switch


// 타입 패턴 매칭
Object obj = getObject();
String result = switch (obj) {
case Integer i -> "정수: " + i;
case String s -> "문자열: " + s;
case null -> "null";
default -> "알 수 없는 타입";
};

// 가드 조건 (when)
String formatted = switch (obj) {
case String s when s.isEmpty() -> "빈 문자열";
case String s when s.length() > 10 -> "긴 문자열: " + s;
case String s -> "문자열: " + s;
default -> "기타";
};


Record Patterns


record Point(int x, int y) {}
record Rectangle(Point topLeft, Point bottomRight) {}

// 중첩 레코드 분해
void printRect(Object obj) {
if (obj instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) {
System.out.printf("좌상단: (%d, %d), 우하단: (%d, %d)%n", x1, y1, x2, y2);
}
}

// switch에서 레코드 패턴
String describe(Object obj) {
return switch (obj) {
case Point(int x, int y) when x == 0 && y == 0 -> "원점";
case Point(int x, int y) -> "점 (" + x + ", " + y + ")";
default -> "기타";
};
}


Sequenced Collections


// 순서가 있는 컬렉션의 통합 API
SequencedCollection<String> list = new ArrayList<>();
list.addFirst("first");
list.addLast("last");
String first = list.getFirst();
String last = list.getLast();
list.removeFirst();
list.removeLast();

// 역순 뷰
SequencedCollection<String> reversed = list.reversed();

// SequencedMap
SequencedMap<String, Integer> map = new LinkedHashMap<>();
map.putFirst("a", 1);
map.putLast("z", 26);
Map.Entry<String, Integer> firstEntry = map.firstEntry();


String Templates (Preview)


// 문자열 템플릿 (--enable-preview 필요)
String name = "홍길동";
int age = 30;

String message = STR."이름: {name}, 나이: {age}";
// 결과: "이름: 홍길동, 나이: 30"

// 멀티라인
String json = STR."""
{
"name": "{name}",
"age": {age}
}
""";


Scoped Values (Preview)


// ThreadLocal 대안 (불변, 상속 가능)
private static final ScopedValue<User> CURRENT_USER = ScopedValue.newInstance();

void processRequest(User user) {
ScopedValue.where(CURRENT_USER, user).run(() -> {
handleRequest();
});
}

void handleRequest() {
User user = CURRENT_USER.get(); // 현재 스코프의 User
}


Virtual Threads vs Platform Threads








항목Platform ThreadVirtual Thread
메모리~1MB/스레드~수KB/스레드
생성 개수수천 개수백만 개
적합한 작업CPU 바운드I/O 바운드
스케줄링OS 커널JVM


마이그레이션 가이드



  • Java 17 → 21: 대부분 호환

  • synchronized → ReentrantLock (Virtual Thread 성능)

  • ThreadLocal → ScopedValue 검토