← 返回首页

Project Loom与虚拟线程

📂 java ⏱ 2 min 221 words

Project Loom与虚拟线程

Project Loom引入虚拟线程(Virtual Threads),以极低的开销实现高并发,是Java并发模型的重大革新。

虚拟线程基础

// 创建虚拟线程
Thread virtualThread = Thread.ofVirtual().name("vt-1").start(() -> {
    System.out.println("Running in virtual thread");
});

// 使用虚拟线程执行器
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 100000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}

结构化并发

// 结构化并发(预览特性)
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Subtask<String> user = scope.fork(() -> findUser(userId));
    Subtask<Order> order = scope.fork(() -> fetchOrder(orderId));

    scope.join();           // 等待所有任务完成
    scope.throwIfFailed();  // 处理异常

    return new Response(user.get(), order.get());
}

虚拟线程 vs 平台线程

/**
 * 对比:
 * 平台线程:1:1映射OS线程,创建成本高
 * 虚拟线程:M:N映射,创建成本极低
 */
// 创建10万个平台线程 - 可能OOM
for (int i = 0; i < 100000; i++) {
    new Thread(() -> doWork()).start(); // 内存不足
}

// 创建10万个虚拟线程 - 轻松实现
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < 100000; i++) {
        executor.submit(() -> doWork()); // 正常运行
    }
}

实战场景

高并发HTTP服务

// Spring Boot虚拟线程配置
spring:
  threads:
    virtual:
      enabled: true

// 或手动配置
@Bean
public TomcatProtocolHandler<?> protocolHandler() {
    ProtocolHandler handler = new NioProtocolHandler();
    handler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
    return handler;
}

数据库连接池

// HikariCP虚拟线程配置
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(100);
// 虚拟线程环境下可适当增大连接池

// 虚拟线程中的阻塞操作自动释放载体线程
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> {
        // 阻塞操作会自动释放载体线程
        Connection conn = dataSource.getConnection();
        // ...执行SQL
    });
}

注意事项

/**
 * 虚拟线程使用注意:
 * 1. 不要池化虚拟线程(创建成本极低)
 * 2. 避免在虚拟线程中使用synchronized(会pin载体线程)
 * 3. 使用ReentrantLock替代synchronized
 * 4. 不适合CPU密集型任务
 */

性能对比

// 基准测试
// 平台线程:1000并发,吞吐量 1000 req/s
// 虚拟线程:100000并发,吞吐量 50000 req/s

// 内存占用
// 平台线程:1MB/线程 * 1000 = 1GB
// 虚拟线程:1KB/线程 * 100000 = 100MB

小结

虚拟线程以极低的开销实现了百万级并发,是Java并发编程的革命性进步。