CodeWalk

Java 21虚拟线程Virtual Threads原理与使用

作者:苦行僧 · 2026-05-30 12:55

请详细解释Java 21正式发布的虚拟线程(Virtual Threads,Project Loom)。虚拟线程与传统平台线程(OS线程)的区别是什么?如何使用虚拟线程?虚拟线程的底层调度原理(M:N模型、ForkJoinPool、Continuation)是什么?适用场景和注意事项有哪些?

回答

苦行僧

什么是虚拟线程

虚拟线程是JDK 21正式发布(JEP 444)的轻量级线程,由JVM管理而非操作系统。

  • 平台线程(Platform Thread):映射到OS线程,创建、切换成本高
  • 虚拟线程(Virtual Thread):数百万个虚拟线程复用到少量平台线程(M:N调度)

使用方法

// 方式1:Thread.ofVirtual()
Thread vThread = Thread.ofVirtual()
    .name("vt-").start(() -> System.out.println("虚拟线程"));

// 方式2:Executors.newVirtualThreadPerTaskExecutor()
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> { /* 任务 */ });
}

// 方式3:Thread.startVirtualThread(Runnable)
Thread.startVirtualThread(() -> { ... });

底层原理

  1. Continuation:虚拟线程的核心是Continuation(协程),可暂停和恢复
  2. ForkJoinPool调度:虚拟线程挂载到ForkJoinPool的平台线程上运行
  3. 固定(Pinning):当虚拟线程执行synchronized块或native方法时,会被固定到平台线程(无法卸载)
  4. VThread Carrier线程:真正执行任务的平台线程,虚拟线程在park/unpark时切换

适用场景与注意事项

适用

  • 大量IO密集型任务(Web服务器、微服务、数据库调用)
  • 每个请求一个线程的模型(如Tomcat)
  • 高并发WebFlux的替代方案(用同步API达到响应式性能)

注意事项

  • 避免synchronized块中做阻塞操作(使用ReentrantLock替代)
  • 避免线程池(虚拟线程本身已轻量,无需池化)
  • ThreadLocal谨慎使用(虚拟线程数量多,ThreadLocal内存开销大)
  • CPU密集型任务不适合(平台线程更合适)