0
0
Lập trình
Admin Team
Admin Teamtechmely

Khám Phá Virtual Thread trong Java 21: Giải Pháp Mới cho Multithreading

Đăng vào 1 tuần trước

• 4 phút đọc

1. Sự Phát Triển của Mô Hình Thread

Trong quá trình làm việc, nhiều lập trình viên đã tiếp xúc với nhiều mô hình xử lý đa luồng (Multithreading). Có thể phân loại chúng thành bốn mô hình chính như sau:

  • Synchronous Blocking: Mô hình đơn giản nhưng hiệu suất bị hạn chế do không thể xử lý song song.
  • Asynchronous Blocking: Giúp cải thiện một phần hiệu suất nhưng vẫn còn nhiều nhược điểm.
  • Asynchronous Partially Non-Blocking: Đưa ra các giải pháp để cải thiện sự phức tạp nhưng không phải lúc nào cũng mang lại hiệu quả tối ưu.
  • Fully Non-Blocking (Mô hình Reactive): Đối với bài toán yêu cầu IO, đây là giải pháp mạnh mẽ nhưng đi kèm là sự phức tạp trong lập trình.

Để khắc phục được những nhược điểm của lập trình Reactive, Java 21 giới thiệu một giải pháp mới, đơn giản hơn: Virtual Thread.

2. Virtual Thread là gì?

Virtual Thread là một loại luồng nhẹ (lightweight thread) có khả năng sử dụng tài nguyên hiệu quả hơn so với Platform Thread. Khi một Virtual Thread thực hiện một cuộc gọi IO bị chặn (blocking I/O call), nó sẽ chờ nhận phản hồi trong khi đó, Platform Thread sẽ được trả lại cho Pool để xử lý các tác vụ khác. Điều này cho phép hệ thống quản lý một khối lượng lớn tác vụ đồng thời.

3. So Sánh giữa Virtual Thread và Platform Thread

Trước khi Virtual Thread xuất hiện, Java chủ yếu sử dụng Platform Thread, từng được liên kết chặt chẽ với OS Thread. Điều này gây ra những vấn đề như:

  • Tiêu tốn tài nguyên lớn: Mỗi Platform thread tiêu tốn khoảng 1MB kích thước stack.
  • Vấn đề về khả năng mở rộng (Scalability Issues): Số lượng thread bị giới hạn bởi số lượng OS thread.
  • Độ phức tạp: Khó khăn trong việc xử lý mã nguồn có khả năng mở rộng.

Ngược lại, Virtual Thread cũng được liên kết với OS Thread nhưng khi thực hiện các cuộc gọi bị chặn, OS Thread sẽ được trả về Pool, cho phép thực hiện các tác vụ khác.

Lưu ý: Virtual Thread không nhanh hơn Platform Thread mà chỉ giúp tiết kiệm tài nguyên, từ đó tăng khả năng qua các tác vụ (throughput).

4. Tính Tiết Kiệm Tài Nguyên của Virtual Thread

Với Virtual Thread, bạn có thể quản lý nhiều tác vụ cùng lúc mà không lo về tài nguyên. Ví dụ, với 1000 OS thread trong Pool và 1000 tác vụ chạy cùng lúc có thực hiện blocking IO call:

  • Với Platform Thread, tất cả 1000 OS thread đều phải chờ khi gặp blocking call.
  • Với Virtual Thread, OS thread sẽ được trả về Pool cho các tác vụ mới, giúp tăng khả năng xử lý.

5. Ví Dụ Thực Tế

Để khởi tạo Virtual Thread, bạn có thể làm như sau:

java Copy
Thread.startVirtualThread(() -> {
 // Do some work
 System.out.println("Đang chạy trong virtual thread: " +  Thread.currentThread());
});
java Copy
ExecutorService myExecutor = Executors.newVirtualThreadPerTaskExecutor();
Future<?> future = myExecutor.submit(() -> System.out.println("Chạy trong thread"));
future.get();
System.out.println("Nhiệm vụ hoàn thành");

Kiểm tra khả năng chạy 1 triệu Virtual Thread:

java Copy
public static void main(String[] args) throws InterruptedException {
        Instant start = Instant.now();
        Set<Long> vThreadIds = new HashSet<>();

        var vThreads = IntStream.range(0, 1_000_000)
                .mapToObj(i -> Thread.ofVirtual().unstarted(() -> {
                    vThreadIds.add(Thread.currentThread().getId());
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                })).toList();

        vThreads.forEach(Thread::start);
        for (var thread : vThreads) {
            thread.join();
        }

        Instant end = Instant.now();
        System.out.println("Thời gian =" + Duration.between(start, end).toMillis() + " ms");
        System.out.println("Số lượng vThreads độc đáo đã sử dụng: " + vThreadIds.size());
    }

Kết quả:

  • Thời gian = 4482 ms
  • Số lượng vThreads độc đáo đã sử dụng: 1000000

6. Lưu Ý với Virtual Thread

Virtual Thread thích hợp cho các tác vụ sử dụng blocking call. Trong trường hợp sử dụng synchronize, hiệu suất sẽ bị giảm do JVM không thể xác định liệu mã trong block có bị chặn hay không. Để khắc phục, nên sử dụng Lock thay vì synchronize.

Cần lưu ý rằng, khi thực hiện các cuộc gọi đến file hoặc mạng, JVM có thể xử lý 1 triệu request nhưng không chắc chắn hệ điều hành có cho phép thực hiện tất cả các cuộc gọi này hay không.

Bonus: Cơ Chế Implement của Virtual Thread

Với Virtual Thread, cơ chế chuyển đổi ngữ cảnh (Context Switching) được xử lý bởi JVM thay vì hệ điều hành. JVM quản lý hàng nghìn Virtual Thread thông qua Multiplexing vào một số Platform Thread nhỏ hơn, làm tối ưu hóa sử dụng tài nguyên từ các OS thread.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào