多线程之虚拟线程(协程)

张开发
2026/5/6 16:41:23 15 分钟阅读
多线程之虚拟线程(协程)
什么是协程通俗版想象你去餐厅吃饭传统线程就像每个顾客都有一个专属服务员全程陪同点菜、等菜、结账服务员不能离开。如果餐厅里有100个顾客就需要100个服务员成本很高。协程只有一个服务员一个真实的物理线程但他可以同时服务多个顾客。给第1位顾客点完菜后服务员先去后厨下单然后立刻去服务第2位顾客等第1位顾客的菜好了服务员再过去上菜。这样一个服务员就能高效地处理多个顾客省时省力。在编程里协程就是一种比线程更轻量级的并发单元。它可以在单个操作系统线程上“同时”执行多个任务当一个任务需要等待比如读写文件、网络请求时协程会自动“挂起”自己让出线程去执行其他协程等条件满足后再“恢复”继续执行。Java 中的协程实现Java 长期以来没有原生的协程主要靠第三方库如 Quasar、Kilim模拟。但从Java 19 开始官方通过 Project Loom 引入了虚拟线程这就是 Java 原生的协程实现。虚拟线程由 JVM 管理数量可以轻松创建成千上万个而不会耗尽系统资源。虚拟线程协程的优点极轻量一个虚拟线程占用内存仅几百字节而传统线程平台线程需要几兆。可以创建百万级虚拟线程适合高并发场景。简化异步编程传统异步编程往往需要回调、Future、CompletableFuture代码复杂且难以调试。虚拟线程允许你用同步阻塞的代码风格但底层却是非阻塞的大大降低了编程复杂度。提高吞吐量在 IO 密集型应用中虚拟线程在等待 IO 时自动让出平台线程平台线程可以继续执行其他虚拟线程从而提升 CPU 利用率。与现有代码兼容虚拟线程是java.lang.Thread的子类大部分现有代码无需修改即可迁移。虚拟线程的缺点需要 JDK 版本支持至少 JDK 19正式特性在 JDK 21 中稳定老项目升级有成本。调试工具尚不完善由于虚拟线程数量巨大传统的线程转储thread dump可能会爆炸需要新的诊断工具。某些 API 的兼容问题涉及ThreadLocal大量使用时可能带来内存压力因为每个虚拟线程都有自己的ThreadLocal。使用synchronized块或本地方法时可能会导致虚拟线程固定pinned在平台线程上暂时失去轻量优势。实际开发中的使用场景Web 服务器处理 HTTP 请求每个请求分配一个虚拟线程代码像传统的阻塞式编程一样简单但能支撑超高并发。微服务/API 网关大量对外部服务的网络调用虚拟线程让等待响应的时间被充分利用。数据库访问JDBC 调用是阻塞的但在虚拟线程中阻塞不会浪费平台线程。批处理/任务调度需要并发执行大量 IO 操作的任务如文件处理、消息消费。案例代码Java 21 虚拟线程下面用虚拟线程模拟一个高并发场景同时发起 10,000 个任务每个任务模拟一次网络请求等待 1 秒。importjava.util.concurrent.Executors;importjava.util.stream.IntStream;publicclassVirtualThreadDemo{publicstaticvoidmain(String[]args){// 方式1直接启动虚拟线程Thread.startVirtualThread(()-{System.out.println(Hello from virtual thread: Thread.currentThread());});// 方式2使用虚拟线程的 ExecutorServicetry(varexecutorExecutors.newVirtualThreadPerTaskExecutor()){IntStream.range(0,10_000).forEach(i-{executor.submit(()-{// 模拟 IO 操作例如数据库查询、HTTP 调用Thread.sleep(1000);// 这里会挂起虚拟线程但不会阻塞底层平台线程System.out.println(Task i completed by Thread.currentThread());returni;});});}// 自动等待所有任务完成并关闭}}代码解释Thread.startVirtualThread()快速创建一个虚拟线程执行简单任务。Executors.newVirtualThreadPerTaskExecutor()返回一个执行器每次提交的任务都会启动一个新的虚拟线程。10,000 个任务每个都sleep(1000)如果用传统线程会耗尽系统资源而虚拟线程瞬间完成且底层可能只用了少量平台线程。Thread.sleep()在虚拟线程中是非阻塞的它会让出平台线程等到 1 秒后再恢复。运行效果你会在控制台看到大量虚拟线程并发执行程序很快结束内存占用极低。总结协程 用户态轻量级线程由编程语言或框架调度而非操作系统。Java 虚拟线程是官方协程实现让高并发编程变得简单高效。适合IO 密集型应用能极大简化代码提升资源利用率。使用时注意 JDK 版本和少数特殊场景如synchronized固定问题但在绝大多数业务代码中它几乎可以无缝替换传统线程。如果你正在开发高并发服务不妨尝试将项目升级到 JDK 21 并开始使用虚拟线程感受“百万级并发”带来的震撼。

更多文章