Backend

99 Ngày Java — Ngày 68: Virtual threads trên Java 21

SSite Admin
2 tháng 10, 2026 2 phút đọc 4 lượt xem
99 Ngày Java — Ngày 68: Virtual threads trên Java 21

Virtual thread là Thread nhẹ do JVM quản lý, đã là tính năng chính thức trong Java 21. Ta có thể viết mã chờ I/O theo kiểu tuần tự dễ đọc mà vẫn phục vụ nhiều request đồng thời. Nó không làm phép tính CPU nhanh hơn và không xóa giới hạn database, API hay bộ nhớ.

Virtual threads trên Java 21

1. Tạo một virtual thread cho mỗi task

Executors.newVirtualThreadPerTaskExecutor() tạo một virtual thread cho mỗi task, không phải pool virtual thread cố định. Đóng executor sau khi hoàn tất để chờ các task kết thúc. Tránh đặt ThreadLocal lớn trên hàng chục nghìn thread; chi phí tích lũy vẫn đáng kể.

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    Future<String> result = executor.submit(() -> fetchPage(url));
    System.out.println(result.get());
}

2. Chờ I/O là use case chính

Khi một virtual thread chờ một thao tác I/O có hỗ trợ, JVM có thể nhường carrier platform thread cho việc khác. Tác vụ CPU vẫn cần CPU; chạy thêm thread không tăng số lõi. Giữ giới hạn kết nối DB, rate limit và semaphore cho tài nguyên ngoài dù số virtual thread rất lớn.

Semaphore permits = new Semaphore(20);
permits.acquire();
try { return callPartner(); }
finally { permits.release(); }

3. Pinning và quan sát

Trên Java 21, một virtual thread có thể bị pin vào carrier khi chặn bên trong vùng synchronized hoặc gọi native code. Pinning kéo dài làm giảm khả năng mở rộng; không phải cứ dùng synchronized là lỗi nếu vùng đó ngắn. Dùng JFR hoặc jcmd để quan sát khi tải thật, rồi đưa thao tác chờ dài ra khỏi vùng synchronized.

// Avoid holding this monitor during a slow request.
synchronized (cacheGuard) {
    updateLocalState();
}
String response = callPartner();

4. Structured concurrency vẫn preview

StructuredTaskScope nhóm các task con theo phạm vi để chờ, hủy và xử lý lỗi có cấu trúc. Trong Java 21, JEP 453 là preview: ví dụ dùng nó phải bật --enable-preview khi biên dịch và chạy. Không trình bày nó như API production mặc định; với mã ổn định, dùng ExecutorService và hợp đồng hủy rõ ràng.

  • Đo throughput và latency khi chờ I/O; đo CPU riêng.

  • Tải cao vẫn cần giới hạn kết nối, memory và số request đang xử lý.

Virtual thread giúp kiểu lập trình đồng bộ dễ đọc mở rộng tốt hơn với I/O chờ lâu. Hãy giới hạn tài nguyên thật và đo pinning. Ngày 69 xem cách mang dữ liệu theo luồng mà không rò rỉ.

Tài liệu đối chiếu

  • https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html

  • https://openjdk.org/jeps/444

  • https://openjdk.org/jeps/453

S

Site Admin

Engineer and writer. Building things with TypeScript and distributed systems.

Bình luận (0)

Bạn cần đăng nhập bằng Google để bình luận.

Hãy là người bình luận đầu tiên.

Bài viết liên quan

99 Ngày Spring — Ngày 69: Chuẩn hóa error handling

Thiết kế mã lỗi ổn định, ProblemDetail, thông điệp i18n và correlation ID xuyên request.

3 thg 10, 20262 phút4
99 Ngày Java — Ngày 69: ThreadLocal và bất biến

Hiểu dữ liệu gắn luồng, dọn ThreadLocal trong pool và dùng đối tượng bất biến để giảm chia sẻ trạng thái.

3 thg 10, 20262 phút5
99 Ngày Spring — Ngày 68: i18n trong Spring

Dùng MessageSource, LocaleResolver và thông điệp validation để trả API đa ngôn ngữ nhất quán.

2 thg 10, 20262 phút7