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ớ.

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
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.


