Java 虚拟线程(Virtual Threads)

JDK 21(2023年9月 LTS)正式发布虚拟线程

虚拟线程(Virtual Threads)是 协程 在 Java 中的实现,由 Project Loom 孵化而来。

什么是虚拟线程?

虚拟线程是 JVM 管理的轻量级线程,由 JVM 在少量平台线程(载体线程/Carrier Thread)上调度,而非 OS 内核。

  • 平台线程(Platform Thread)= 传统 java.lang.Thread,映射为 OS 线程
  • 虚拟线程(Virtual Thread)= 由 JVM 调度的轻量级线程,多个虚拟线程复用一个平台线程

如何使用

方式一:虚拟线程执行器(推荐)

// JDK 21+:每个任务一个虚拟线程,无需池化
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
 
// 使用方式与普通线程池完全一致
executor.submit(() -> {
    // 处理 I/O 密集型任务
    String result = httpClient.send(request, BodyHandlers.ofString());
    return result;
});

方式二:直接启动

Thread vThread = Thread.startVirtualThread(() -> {
    System.out.println("Hello from virtual thread!");
});

方式三:Thread.Builder

Thread vThread = Thread.ofVirtual()
    .name("my-virtual-thread")
    .start(() -> {
        // 任务逻辑
    });

虚拟线程 vs 平台线程

特性平台线程(OS 线程)虚拟线程
调度OS 内核调度JVM 用户态调度
栈大小~1MB(固定)~几 KB(可动态扩展)
最大数量几千 ~ 几万数百万
创建成本高(系统调用)极低(纯内存操作)
阻塞代价阻塞 = 线程被挂起(浪费 OS 资源)阻塞 = 切换到其他虚拟线程(零成本)
适用场景CPU 密集型大量 I/O 等待型任务

虚拟线程的本质:面向 I/O 密集型场景

虚拟线程的核心思想是:每个请求/任务一个线程,而不是从池中借用一个线程

// 传统方式:线程池限制并发
ExecutorService pool = Executors.newFixedThreadPool(200);
for (Request request : requests) {
    pool.submit(() -> handleRequest(request));
}
 
// 虚拟线程方式:每个请求一个虚拟线程,无需池化
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    for (Request request : requests) {
        executor.submit(() -> handleRequest(request));
    }
}

局限性

虚拟线程 ≠ 万能药

限制说明
CPU 密集型不适合,无法利用更多 CPU 核心,仍需平台线程池控制并发
synchronized pinning虚拟线程在 synchronized 块内无法被卸载,会钉住载体线程(JDK 21 已部分修复:ReentrantLock 无此问题)
ThreadLocal虚拟线程支持 ThreadLocal,但创建海量虚拟线程时可能导致内存压力(慎用)
native 方法调用 JNI 时虚拟线程会被钉住

最佳实践

// ✅ 虚拟线程 + 信号量控制并发数(混合模式)
// 适用于既有 I/O 等待又是 CPU 密集的混合场景
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    Semaphore semaphore = new Semaphore(100);  // 控制并发度
    for (Task task : tasks) {
        executor.submit(() -> {
            semaphore.acquire();
            try {
                task.process();
            } finally {
                semaphore.release();
            }
        });
    }
}

相关笔记