Java 21 新特性:虚拟线程与结构化并发实战
·
Java 21 新特性:虚拟线程与结构化并发实战
1. 虚拟线程(Virtual Threads)
概念:轻量级线程,由 JVM 管理而非操作系统,显著降低创建和切换开销。
优势:
- 支持百万级线程并发
- 简化高吞吐量 I/O 密集型应用
- 兼容传统
ThreadAPI
实战示例:创建虚拟线程
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
// 提交多个并发任务
executor.submit(() -> processTask("Task1"));
executor.submit(() -> processTask("Task2"));
}
void processTask(String name) {
System.out.println(Thread.currentThread() + " 执行: " + name);
}
输出:
VirtualThread[#1]/runnable@ForkJoinPool-1-worker-1 执行: Task1
VirtualThread[#2]/runnable@ForkJoinPool-1-worker-2 执行: Task2
2. 结构化并发(Structured Concurrency)
概念:通过父子任务关系管理并发生命周期,确保任务组合的可靠性和可观测性。
核心类:StructuredTaskScope(需导入 jdk.incubator.concurrent 模块)
优势:
- 自动传播错误和取消信号
- 避免线程泄漏
- 简化资源清理
实战示例:并行请求聚合
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// 创建子任务
Future<String> userTask = scope.fork(() -> fetchUserData());
Future<String> orderTask = scope.fork(() -> fetchOrderData());
scope.join(); // 等待所有子任务完成
scope.throwIfFailed(); // 检查异常
// 合并结果
String result = "用户: " + userTask.resultNow() + " | 订单: " + orderTask.resultNow();
System.out.println(result);
}
String fetchUserData() throws InterruptedException {
Thread.sleep(500); // 模拟网络延迟
return "张三";
}
String fetchOrderData() throws InterruptedException {
Thread.sleep(300);
return "订单#1001";
}
输出:
用户: 张三 | 订单: 订单#1001
3. 综合实战:虚拟线程 + 结构化并发
场景:并行处理文件下载和日志记录,任一失败则整体取消。
void downloadAndLog(String url, String logPath) {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// 虚拟线程执行下载
Future<byte[]> downloadTask = scope.fork(() -> {
try (InputStream in = new URL(url).openStream()) {
return in.readAllBytes();
}
});
// 虚拟线程执行日志
Future<Void> logTask = scope.fork(() -> {
Files.writeString(Path.of(logPath), "开始下载: " + url);
return null;
});
scope.join();
scope.throwIfFailed();
System.out.println("下载完成! 大小: " + downloadTask.resultNow().length + " 字节");
} catch (Exception e) {
System.err.println("任务失败: " + e.getMessage());
}
}
关键点:
- 任一子任务失败时,
ShutdownOnFailure自动取消其他任务 - 虚拟线程优化 I/O 阻塞操作
- 资源通过
try-with-resources自动释放
4. 性能对比
传统线程池 vs 虚拟线程(10,000 个并发任务):
| 指标 | 平台线程池 | 虚拟线程 |
|---|---|---|
| 内存占用 | $\approx$ 1GB | $\approx$ 20MB |
| 创建时间 | $\approx$ 2s | $\approx$ 0.1s |
| CPU 利用率 | 高 | 低 |
5. 使用建议
- 适用场景:
- 高并发微服务(如 HTTP 服务器)
- 批量数据处理
- 并行 I/O 操作
- 避坑指南:
- 避免在计算密集型任务中使用
- 勿用
synchronized阻塞虚拟线程 - 启用预览特性:
javac --release 21 --enable-preview Main.java
通过虚拟线程和结构化并发,Java 21 将并发编程复杂度从系统级降至应用级,大幅提升开发效率与可维护性。
更多推荐
所有评论(0)