当前位置: 首页 > news >正文

面试官:为什么没有虚拟线程池?

Java 官方文档明确指出:

Do not pool virtual threads.

虚拟线程不是昂贵资源,永远不应该被池化。

应该为每个任务创建一个新的虚拟线程,它们应该是短暂的、任务级别的。

这是为什么呢?为什么只有虚拟线程 Virtual Thread,却没有虚拟线程池 Virtual Thread Pool 呢?

主要原因

之所以只有虚拟线程是因为,虚拟线程创建成本极低,低到其创建成本远小于线程池的管理成本。

也就是说,线程池的管理成本远远大于虚拟线程的创建成本,所以使用虚拟线程池是一个不划算的操作。

具体来说,传统平台线程的创建涉及分配大量的栈内存(通常~1MB)并与操作系统交互,开销很大。池化是为了复用这些“昂贵”的线程,避免反复申请资源。而虚拟线程由 JVM 在用户态管理,初始栈空间很小(约几百字节),创建和销毁的代价极低,池化带来的收益远小于管理池本身的复杂度。

“用完就扔”比“池化复用”更高效、更简单。一个线程约等于几千个虚拟线程。

一任务一虚线程的理念

官方推荐并为每个任务创建一个全新的虚拟线程,例如通过 Executors.newVirtualThreadPerTaskExecutor(),任务完成后虚拟线程即被丢弃。这种模式代码更清晰,避免了因线程复用可能带来的线程局部变量(ThreadLocal)污染等问题,也无需担心池的大小调优等问题。

最佳实现代码:

// 无需池化 - 直接创建
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {IntStream.range(0, 10_000).forEach(i -> {executor.submit(() -> {Thread.sleep(Duration.ofSeconds(1));return i;});});
} // 自动关闭(所有虚拟线程完成即销毁)

ExecutorService 并不是一个传统意义上的“池”,你可以把它理解为一个虚拟线程工厂。每次 submit 一个任务,它都会立即创建一个新的虚拟线程来执行该任务,它内部并不维护(一个可复用的)线程队列。

如何限制并发?

单进程百万虚拟线程的情况下, JVM 内存是完全无压力的。如果你还是担心太多的虚拟线程会导致程序崩溃,在特定的场景可以使用 Semaphore 等技术来实现局部限流,例如以下代码这样:

// 使用信号量而非线程池来限制对某个资源的并发访问
Semaphore semaphore = new Semaphore(100000); // 限制最大并发数为100000try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {for (int i = 0; i < 10_000; i++) {executor.submit(() -> {semaphore.acquire(); // 获取许可,若已达上限则阻塞等待try {// 访问受保护的资源或执行需要限流的操作callLimitedService();} finally {semaphore.release(); // 释放许可}});}
}

小结

虚拟线程 Virtual Thread 因为其创建成本极低(约几百字节),所以不会完全不需要使用池化技术来实现,因为池化技术的本质是复用那些“昂贵”的线程,避免反复申请资源的。如果要局部限流虚拟线程可以使用 Semaphore 来实现。

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:场景题、SpringAI、SpringAIAlibaba、并发编程、MySQL、Redis、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、JVM、设计模式、消息队列、Dify、Coze、AI常见面试题等。

http://www.gsyq.cn/news/10983.html

相关文章:

  • 从安装到中文界面,一文带你玩转 DaVinci Resolve 20(零基础也能搞定)
  • linux手动安装阿里云Logtail采集Nginx访问日志
  • 古代史
  • HarmonyOS 5.0+ 安全加密与数据存储最佳实践指南
  • EV论文修改工作
  • B端界面设计的核心逻辑:效率优先还是体验优先?
  • 质数(埃氏筛、欧拉筛)
  • HarmonyOS数据持久化:Preferences轻量级存储实战
  • 有理数类的问题回答
  • 案例分享 | 芯片企业官网优化
  • Kali Linux 2025.3 发布 (Vagrant Nexmon) - 领先的渗透测试发行版
  • C语言多线程同步详解:从互斥锁到条件变量
  • LazyForEach性能优化:解决长列表卡顿问题
  • Redis数据结构的最佳实践 - 公众号
  • java函数式编程的学习01
  • 25Java基础之IO(二)
  • 【P2860】[USACO06JAN] Redundant Paths G - Harvey
  • 【CV】GAN代码解析 image_folder.py
  • react使用ctx和reducer代替redux
  • 算法学习笔记:支配对
  • 西电PCB设计指南第5章学习笔记
  • ImageMagick - 关于图片压缩,通过dk整理的一些可用指令 - window64
  • 黄金、原油期货数据API对接文档
  • 我的笔记方案
  • 聊聊前序、中序、后序表达式
  • flink书籍 - --
  • Asp.Net Core 鉴权授权
  • 遇到一款无人机,上面有安全模式和强力模式,十分迷惑二者区别,问了技术说是和碰撞指数有关,涨知识
  • 直播预告| PostgreSQL 与 IvorySQL 在云原生时代的演进与实践
  • 金蝶AAS (Apusic Application Server) v10 部署SuperMap iServer 2025 详细教程