Project Loom与虚拟线程
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并发编程的革命性进步。