# 05.虚拟线程原理及性能分析

文章虚拟线程原理及性能分析 (opens new window) 详细介绍了JDK21最新的虚拟线程的优势,对于单机提升服务吞吐量有很大的提升。

什么是虚拟线程

区别于虚拟线程,传统的线程对象叫做平台线程(platform thread)。平台线程在底层 OS 线程上运行 Java 代码,并在代码的整个生命周期中占用该 OS 线程,因此平台线程的数量受限于 OS 线程的数量。虚拟线程是 java.lang.Thread 的一个实例,它在底层 OS 线程上运行 Java 代码,但不会在代码的整个生命周期中占用该 OS 线程。也就是说,多个虚拟线程可以在同一个 OS 线程上运行其 Java 代码,可以有效地共享该线程。平台线程独占宝贵的 OS 线程,而虚拟线程则不会,因此虚拟线程的数量可以比 OS 线程的数量多得多,执行阻塞任务的整体吞吐量也就大了很多。 但如果上述任务不是简单的sleep 1s,而是计算了1s(例如做矩阵计算或数组排序等),用线程池和虚拟线程的执行时间区别就没有那么大。原因是虚拟线程虽然可以带来更大的吞吐量,但并不能让单个任务计算得更快,当使用平台线程执行任务已经让cpu没有任何空闲时,切换虚拟线程来执行也不会带来任何收益。 虚拟线程可以发挥的最大作用是,可以让采用单请求单线程(thread-per-request)的方式编写的服务器程序最大化地利用CPU计算资源 。 其原因在于服务器程序有两大特点,一是需要处理较大吞吐量的请求,二是请求处理的过程大多是由IO密集型逻辑组成,这就导致采用平台线程实现的单请求单线程编写方式,可能会有大量的IO阻塞占据了平台线程资源,从而不能充分利用CPU资源。我们在使用真实应用压测时观察到,当服务请求IO耗时增大时,使用虚拟线程的吞吐量会明显高于线程池,尤其是当服务下游依赖出现故障导致耗时增大时,虚拟线程带来的服务可用性提升会非常明显。 有些情况下,服务端开发者为了充分利用cpu硬件资源,会考虑放弃单请求单线程的编程风格,而采用基于netty、actor等异步框架来构建服务。这样虽然它消除了由于OS线程稀缺性带来的吞吐量限制,但代价很高:它需要异步编程风格,没有专用线程,开发人员必须将请求处理逻辑分解成小阶段,通常是lambda表达式或独立的回调handler对象,然后使用API将它们组合成一个顺序管道(例如CompletableFuture或响应式框架),在一定程度上放弃了代码的顺序执行逻辑和代码的可读性。 在异步风格中,请求的每个阶段可能在不同的线程上执行,每个线程以交替方式运行属于不同请求的阶段。这对于理解程序行为有很大的影响:堆栈跟踪不能提供可用的上下文,debug无法跟踪请求处理逻辑,而分析工具无法将请求处理与其调用者相关联。总的来说,除了底层服务框架和一些特定的功能性服务,大部分以业务开发为主导的服务器程序都不会采用这种编程风格进行逻辑开发。详细用法可以参考文章虚拟线程 Virtual Threads (opens new window)

Last Updated: 1/12/2024, 3:25:22 PM
Apache License 2.0 | Copyright © 2022 by xueliang.wu 苏ICP备15016087号