Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- UXUIPrimary
- 백엔드개발자
- 환급챌린지
- 백준
- 국비지원교육
- 패스트캠퍼스
- Spring
- 백엔드
- baekjoon
- 백엔드 부트캠프
- 오픈패스
- UXUI기초정복
- mysql
- 객체지향
- 디자인챌린지
- 내일배움카드
- 디자인교육
- 오픈챌린지
- 국비지원
- KDT
- 디자인강의
- 내일배움캠프
- 티스토리챌린지
- 오블완
- UXUI챌린지
- 국비지원취업
- 부트캠프
- OPENPATH
- Java
- Be
Archives
- Today
- Total
군만두의 IT 공부 일지
[스터디4] 09. 자바 21에서 강화된 언어 및 라이브러리 본문
목차
21장. 자바 21에서 강화된 언어 및 라이브러리
21.6 가상 스레드
- 가상(virtual) 스레드: 처리량이 높은 동시 애플리케이션을 개발할 때 사용할 수 있는 경량(lightweight) 스레드
가상 스레드 개요
- 지금까지는 서버 애플리케이션에서 사용자 요청을 동시에 처리(요청별 스레드)하기 위해 스레드풀링을 사용했다.
- 풀링: 제한된 개수로 스레드를 운용하는 것

14장에서 스레드풀링을 학습했다. 스레드풀에서 초당 200개의 요청을 동시에 처리할 때 10개의 스레드를 사용했다면, 초당 2000개의 요청을 동시에 처리하려면 스레드풀에는 100개의 스레드가 풀링되어야 한다.
- 자바 17까지: 운영체제가 제공하는 플랫폼(platform) 스레드를 래핑했기 때문에 스레드와 플랫폼 스레드가 1:1로 매핑된다.
- 플랫폼 스레드는 비용(CPU 또는 메모리 사용량)이 많이 들기 때문에 스레드의 수를 제한해야 한다.
- 자바 21: 가상 스레드를 제공하는데, 가상 스레드는 플랫폼 스레드와 n:1로 매핑된다.
- CPU를 효율적으로 이용하면서 동시 처리량을 확장할 수 있어 플랫폼 스레드의 부족 문제를 해결할 수 있다.
- 가상 스레드는 CPU에서 계산을 수행하는 동안만 플랫폼 스레드를 사용한다.
- 가상 스레드가 블로킹 I/O 작업(파일 입출력, 네트워킹)을 수행할 경우 일지 중지되지만, 플랫폼 스레드는 다른 가상 스레드의 작업을 처리한다.

*플랫폼 스레드: 스레드와 가상 스레드를 구분하기 위해 스레드를 플랫폼 스레드라고 부른다. (자바 API 도큐먼트)
가상 스레드풀 생성
- 가상 스레드는 플랫폼 스레드에 비해 생성 비용이 저렴하고(하드웨어 자원을 적게 사용하고), 개수에 제한을 받지 않는다.
- 가상 스레드는 스레드풀에서 풀링되어서는 안 되고, 작업 건수별로 새로운 가상 스레드를 생성해서 처리해야 한다.
구분 | 스레드풀 생성 |
플랫폼 스레드풀 | ExecutorService platformExecutor = Executors.newFixedThreadPool(최대 개수); |
가상 스레드풀 | ExecutorService virtualExecutor = Executors.newVirtualThreadPerTaskExecutor(); |
int taskNum = 10000;
// 플랫폼 스레드 100개를 풀링해서 사용하는 스레드풀 생성
ExecutorService threadExecutor = Executors.newFixedThreadPool(100);
work(taskNum, task, threadExecutor);
// 가상 스레드를 사용하는 ExecutorService 생성
ExecutorService virtualThreadExecutor = Executors.newVirtualThreadPerTaskExecutor();
work(taskNum, task, virtualThreadExecutor);
가상 스레드 생성
자바 21부터는 가상 스레드를 생성하기 위해 새로운 정적 메소드 2개가 추가되었다.
리턴 타입 | 정적 메소드 |
Thread | Thread.startVirtualThread(Runnable task) |
Thread.Builder.OfVirtual | Thread.ofVirtual() |
- startVirtualThread() 메소드: 가상 스레드를 생성하고 바로 작업 내용을 실행한다. 생성된 가상 스레드 객체를 리턴한다.
Thread thread = Thread.startVirtualThread(() -> {
// 작업 내용
});
- start() 메소드: 가상 스레드를 생성하고 바로 작업 내용을 실행한다. 생성된 가상 스레드 객체를 리턴한다.
Thread thread = Thread.ofVirtual()
.start(() -> {
// 작업 내용
});
Thread thread = Thread.ofVirtual()
.name("threadName") // 스레드 이름 설정
.start(() -> {
// 작업 내용
});
플랫폼 스레드 생성
스레드를 생성하면 모두 플랫폼 스레드로 생성한다.
Runnable task = ...;
Thread thread = new Thread(task);
자바 21부터는 플랫폼 스레드를 생성하는 방법으로 Thread 클래스에 ofPlatform() 정적 메소드가 추가되었다.
리턴 타입 | 정적 메소드 |
Thread.Builder.OfPlatform | Thread.ofPlatform() |
// 기본(플랫폼 스레드 생성 및 실행)
Thread thread = Thread.ofPlatform()
.start(() -> {
// 작업 내용
});
// 스레드 이름 지정
Thread thread = Thread.ofPlatform()
.name("threadName")
.start(() -> {
// 작업 내용
});
// 데몬 스레드 설정
Thread thread = Thread.ofPlatform()
.daemon()
.start(() -> {
// 작업 내용
});
21.7 순차 컬렉션
- 기존 컬렉션 프레임워크에서는 순서를 갖는 컬렉션들의 공통 상위 인터페이스가 없기 때문에 순서가 있는 컬렉션들이 흩어져 있다.
- 예) Collection ⊃ List/Set, Set ⊃ SortedSet/HashSet 등
- 자바 21은 순서가 있는 컬렉션을 묶고, 공통 API를 제공할 목적으로 순차 컬렉션(Sequenced Collection), 순차 셋(SequencedSet), 순차 맵(SequencedMap) 인터페이스를 추가하고 기존 인터페이스의 상속 관계를 수정했다.

순차 컬렉션
- SequencedCollection: 순서가 있는 List와 Set 컬렉션의 최상위 인터페이스
- 아래 메소드는 순서가 있는 List와 Set 컬렉션에서 모두 사용할 수 있다.
리턴 타입 | 메소드 이름 | 설명 |
void | addFirst(E e) | 첫 번째 요소로 추가 |
void | addLast(E e) | 마지막 요소로 추가 |
E | getFirst() | 첫 번째 요소를 가져오기 |
E | getLast() | 마지막 요소를 가져오기 |
E | removeFirst() | 첫 번째 요소를 제거하기 |
E | removeLast() | 마지막 요소를 제거하기 |
SequencedCollection(E) | reversed() | 요소의 순서를 뒤바꾸기 |
순차 Set
- 순차 Set 컬렉션: 순서가 있으면서 요소의 중복 저장을 허용하지 않는다.
- SequencedCollection의 자식인 SequencedSet 인터페이스를 별도로 상속받는다.
리턴 타입 | 메소드 이름 | 설명 |
SequencedSet<E> | reversed() | 요소의 순서를 뒤바꾸기 |
순차 Map
- SequencedMap: 순서가 있는 Map 컬렉션의 최상위 인터페이스
리턴 타입 | 메소드 이름 | 설명 |
Map.Entry<K, V> | firstEntry() | 첫 번째 엔트리를 가져오기 |
Map.Entry<K, V> | lastEntry() | 마지막 엔트리를 가져오기 |
Map.Entry<K, V> | pollFirstEntry() | 첫 번째 요소를 가져오고, Map에서 제거 |
Map.Entry<K, V> | pollLastEntry() | 마지막 요소를 가져오고, Map에서 제거 |
V | putFirst(K k, V v) | 첫 번째 요소로 추가하기 |
V | putLast(K k, V v) | 마지막 요소로 추가하기 |
SequencedMap<K, V> | reversed() | 엔트리의 순서를 뒤바꾸기 |
SequencedSet<Map.Entry<K, V>> | sequencedEntrySet() | 엔트리를 요소로 하는 SequencedSet 얻기 |
SequencedSet<K> | sequencedKeySet() | 키를 요소로 하는 SequencedSet 얻기 |
SequencedCollection<V> | sequencedValues() | 값을 요소로 하는 SequencedCollection 얻기 |
수정할 수 없는 순차 컬렉션
자바 21에서는 요소를 변경할 수 없도록 수정할 수 없는 순차 컬렉션을 만들기 위해 Collections 클래스에 다음 정적 메소드가 추가되었다.
Collections.unmodifiableSequencedCollection(sequencedCollection)
Collections.unmodifiableSequencedSet(sequencedSet)
Collections.unmodifiableSequencedMap(sequencedMap)
- 3가지 외에 Collection에는 unmodifiableXXX() 메소드들이 정의되어 있다.
- unmodifiableXXX() 메소드: 원본 컬렉션의 요소를 보호하고 싶을 때 이용해서 불변 복제 컬렉션을 만들고 전달한다.
21.8 기본 문자셋 변경
- 자바는 JVM이 실행될 때 운영체제의 환경에 따라 자바 기본 문자셋이 결정되었다.
- 맥OS: UTF-8을 기본 문자셋으로 사용했다.
- 한글 위도우: x-windows-949(MS949)를 사용했다.
- 자바 21부터는 자바 기본 문자셋이 UTF-8로 통일되었기 때문에 운영체제의 환경에 의존하지 않는다.
바이트 수
- 기본 문자셋이 달라지면 숫자와 영어와는 다르게, 한글 문자는 처리 바이트 수가 달라진다.
- MS949: 한글 문자를 2byte로 처리한다.
- UTF-8: 한글 문자를 3byte로 처리한다.
호환성 있는 코드
자바 기본 문자셋이 다르면 바이트 수와 파일 크기가 달라진다. 바이트 수에 민감한 애플리케이션은 자바 기본 문자셋과 상관없이 호환성 있는 코드로 수정할 필요가 있다.
byte[] bytes = "자바".getBytes(); // 바이트 수가 다름
FileWriter writer = new FileWriter(file); // 파일 크기가 다름
// 호환성 있는 코드로 수정(항상 UTF-8 문자셋 사용)
byte[] bytes = "자바".getBytes(Charset.forName("UTF-8"));
FileWriter writer = new FileWriter(file, Charset.forName("UTF-8"));
이 글은 『이것이 자바다』 책을 학습한 내용을 정리한 것입니다.
'프로그래밍 > Java' 카테고리의 다른 글
[스터디7] 01. 스프링 컨텍스트: 빈 정의 (0) | 2025.04.11 |
---|---|
[스터디4] 08. 스트림 요소 처리 (0) | 2025.03.21 |
[스터디4] 07. 멀티 스레드 (0) | 2025.03.11 |
[스터디4] 06. 제네릭 (0) | 2025.03.02 |
[스터디4] 05. 중첩 선언과 익명 객체 (0) | 2025.02.25 |