Java 21 虚拟线程 vs 缓存线程池与固定线程池

news/2025/10/30 13:34:28/文章来源:https://www.cnblogs.com/icodewalker/p/19176772

探索 Java 并发如何从 Java 8 的增强发展到 Java 21 的虚拟线程,从而实现轻量级、可扩展且高效的多线程处理。

引言

并发编程仍然是构建可扩展、响应式 Java 应用程序的关键部分。多年来,Java 持续增强了其多线程编程能力。本文回顾了从 Java 8 到 Java 21 并发的演进,重点介绍了重要的改进以及 Java 21 中引入的具有重大影响的虚拟线程。

从 Java 8 开始,并发 API 出现了显著的增强,例如原子变量、并发映射以及集成 lambda 表达式以实现更具表现力的并行编程。

Java 8 引入的关键改进包括:

  • 线程与执行器
  • 同步与锁
  • 原子变量与 ConcurrentMap

Java 21 于 2023 年底发布,带来了虚拟线程这一重大演进,从根本上改变了 Java 应用程序处理大量并发任务的方式。虚拟线程为服务器应用程序提供了更高的可扩展性,同时保持了熟悉的"每个请求一个线程"的编程模型。

或许,Java 21 中最重要的特性就是虚拟线程。
在 Java 21 中,Java 的基本并发模型保持不变,Stream API 仍然是并行处理大型数据集的首选方式。
随着虚拟线程的引入,并发 API 现在能提供更好的性能。在当今的微服务和可扩展服务器应用领域,线程数量必须增长以满足需求。虚拟线程的主要目标是使服务器应用程序能够实现高可扩展性,同时仍使用简单的"每个请求一个线程"模型。

虚拟线程

在 Java 21 之前,JDK 的线程实现使用的是操作系统线程的薄包装器。然而,操作系统线程代价高昂:

  • 如果每个请求在其整个持续时间内消耗一个操作系统线程,线程数量很快就会成为可扩展性的瓶颈。
  • 即使使用线程池,吞吐量仍然受到限制,因为实际线程数量是有上限的。

虚拟线程的目标是打破 Java 线程与操作系统线程之间的 1:1 关系。
虚拟线程应用了类似于虚拟内存的概念。正如虚拟内存将大的地址空间映射到较小的物理内存一样,虚拟线程允许运行时通过将它们映射到少量操作系统线程来制造拥有许多线程的假象。

平台线程是操作系统线程的薄包装器。
而虚拟线程并不绑定到任何特定的操作系统线程。虚拟线程可以执行平台线程可以运行的任何代码。这是一个主要优势——现有的 Java 代码通常无需修改或仅需少量修改即可在虚拟线程上运行。虚拟线程由平台线程承载,这些平台线程仍然由操作系统调度。

例如,您可以像这样创建一个使用虚拟线程的执行器:

ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();

对比示例

虚拟线程仅在主动执行 CPU 密集型任务时才消耗操作系统线程。虚拟线程在其生命周期内可以在不同的载体线程上挂载或卸载。

通常,当虚拟线程遇到阻塞操作时,它会自行卸载。一旦该阻塞任务完成,虚拟线程通过挂载到任何可用的载体线程上来恢复执行。这种挂载和卸载过程频繁且透明地发生——不会阻塞操作系统线程。

示例 — 源代码

Example01CachedThreadPool.java

在此示例中,使用缓存线程池创建了一个执行器:

var executor = Executors.newCachedThreadPool()
package threads;import java.time.Duration;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;/**** @author Milan Karajovic <milan.karajovic.rs@gmail.com>**/public class Example01CachedThreadPool {public void executeTasks(final int NUMBER_OF_TASKS) {final int BLOCKING_CALL = 1;System.out.println("Number of tasks which executed using 'newCachedThreadPool()' " + NUMBER_OF_TASKS + " tasks each.");long startTime = System.currentTimeMillis();try (var executor = Executors.newCachedThreadPool()) {IntStream.range(0, NUMBER_OF_TASKS).forEach(i -> {executor.submit(() -> {// 模拟阻塞调用Thread.sleep(Duration.ofSeconds(BLOCKING_CALL));return i;});});} catch (Exception e) {throw new RuntimeException(e);}long endTime = System.currentTimeMillis();System.out.println("For executing " + NUMBER_OF_TASKS + " tasks duration is: " + (endTime - startTime) + " ms");}}
package threads;import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;/**** @author Milan Karajovic <milan.karajovic.rs@gmail.com>**/@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Example01CachedThreadPoolTest {@Test@Order(1)public void test_1000_tasks() {Example01CachedThreadPool example01CachedThreadPool = new Example01CachedThreadPool();example01CachedThreadPool.executeTasks(1000);}@Test@Order(2)public void test_10_000_tasks() {Example01CachedThreadPool example01CachedThreadPool = new Example01CachedThreadPool();example01CachedThreadPool.executeTasks(10_000);}@Test@Order(3)public void test_100_000_tasks() {Example01CachedThreadPool example01CachedThreadPool = new Example01CachedThreadPool();example01CachedThreadPool.executeTasks(100_000);}@Test@Order(4)public void test_1_000_000_tasks() {Example01CachedThreadPool example01CachedThreadPool = new Example01CachedThreadPool();example01CachedThreadPool.executeTasks(1_000_000);}}

我 PC 上的测试结果:

Example02FixedThreadPool.java

使用固定线程池创建执行器:

var executor = Executors.newFixedThreadPool(500)
package threads;import java.time.Duration;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;/**** @author Milan Karajovic <milan.karajovic.rs@gmail.com>**/public class Example02FixedThreadPool {public void executeTasks(final int NUMBER_OF_TASKS) {final int BLOCKING_CALL = 1;System.out.println("Number of tasks which executed using 'newFixedThreadPool(500)' " + NUMBER_OF_TASKS + " tasks each.");long startTime = System.currentTimeMillis();try (var executor = Executors.newFixedThreadPool(500)) {IntStream.range(0, NUMBER_OF_TASKS).forEach(i -> {executor.submit(() -> {// 模拟阻塞调用Thread.sleep(Duration.ofSeconds(BLOCKING_CALL));return i;});});}   catch (Exception e) {throw new RuntimeException(e);}long endTime = System.currentTimeMillis();System.out.println("For executing " + NUMBER_OF_TASKS + " tasks duration is: " + (endTime - startTime) + " ms");}}
package threads;import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;/**** @author Milan Karajovic <milan.karajovic.rs@gmail.com>**/@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Example02FixedThreadPoolTest {@Test@Order(1)public void test_1000_tasks() {Example02FixedThreadPool example02FixedThreadPool = new Example02FixedThreadPool();example02FixedThreadPool.executeTasks(1000);}@Test@Order(2)public void test_10_000_tasks() {Example02FixedThreadPool example02FixedThreadPool = new Example02FixedThreadPool();example02FixedThreadPool.executeTasks(10_000);}@Test@Order(3)public void test_100_000_tasks() {Example02FixedThreadPool example02FixedThreadPool = new Example02FixedThreadPool();example02FixedThreadPool.executeTasks(100_000);}@Test@Order(4)public void test_1_000_000_tasks() {Example02FixedThreadPool example02FixedThreadPool = new Example02FixedThreadPool();example02FixedThreadPool.executeTasks(1_000_000);}}

我 PC 上的测试结果:

Example03VirtualThread.java

使用虚拟线程每任务执行器创建执行器:

var executor = Executors.newVirtualThreadPerTaskExecutor()
package threads;import java.time.Duration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;/**** @author Milan Karajovic <milan.karajovic.rs@gmail.com>**/public class Example03VirtualThread {public void executeTasks(final int NUMBER_OF_TASKS) {final int BLOCKING_CALL = 1;System.out.println("Number of tasks which executed using 'newVirtualThreadPerTaskExecutor()' " + NUMBER_OF_TASKS + " tasks each.");long startTime = System.currentTimeMillis();try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {IntStream.range(0, NUMBER_OF_TASKS).forEach(i -> {executor.submit(() -> {// 模拟阻塞调用Thread.sleep(Duration.ofSeconds(BLOCKING_CALL));return i;});});}   catch (Exception e) {throw new RuntimeException(e);}long endTime = System.currentTimeMillis();System.out.println("For executing " + NUMBER_OF_TASKS + " tasks duration is: " + (endTime - startTime) + " ms");}}
package threads;import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;/**** @author Milan Karajovic <milan.karajovic.rs@gmail.com>**/@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Example03VirtualThreadTest {@Test@Order(1)public void test_1000_tasks() {Example03VirtualThread example03VirtualThread = new Example03VirtualThread();example03VirtualThread.executeTasks(1000);}@Test@Order(2)public void test_10_000_tasks() {Example03VirtualThread example03VirtualThread = new Example03VirtualThread();example03VirtualThread.executeTasks(10_000);}@Test@Order(3)public void test_100_000_tasks() {Example03VirtualThread example03VirtualThread = new Example03VirtualThread();example03VirtualThread.executeTasks(100_000);}@Test@Order(4)public void test_1_000_000_tasks() {Example03VirtualThread example03VirtualThread = new Example03VirtualThread();example03VirtualThread.executeTasks(1_000_000);}@Test@Order(5)public void test_2_000_000_tasks() {Example03VirtualThread example03VirtualThread = new Example03VirtualThread();example03VirtualThread.executeTasks(2_000_000);}}

我 PC 上的测试结果:

结论

您可以清楚地看到用于处理所有 NUMBER_OF_TASKS 的不同执行器实现之间的执行时间差异。值得尝试不同的 NUMBER_OF_TASKS 值以观察性能变化。

虚拟线程的优势在处理大量任务时变得尤其明显。当 NUMBER_OF_TASKS 设置为较高的数值时——例如 1,000,000——性能差距是显著的。如下表所示,虚拟线程在处理大量任务时效率要高得多:

我确信,在澄清这一点之后,如果您的应用程序使用并发 API 处理大量任务,您会认真考虑迁移到 Java 21 并利用虚拟线程。在许多情况下,这种转变可以显著提高应用程序的性能和可扩展性。

源代码:GitHub Repository – Comparing Threads in Java 21


【注】本文译自:Java 21 Virtual Threads vs Cached and Fixed Threads

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/950708.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年知名的盾构施工煤矿道岔厂家实力及用户口碑排行榜

2025年知名的盾构施工煤矿道岔厂家实力及用户口碑排行榜 行业概述 随着我国煤矿开采技术的不断进步和盾构施工技术的广泛应用,煤矿道岔作为轨道运输系统中的关键设备,其质量和性能直接影响着煤矿生产的安全与效率。…

揭秘Deepseek:只用GPT-4成本的6%,却做出更聪明的AI?

Deepseek凭MoE技术等黑科技,用GPT-4仅6%成本做出同级别效果!文章揭秘其完整工作流程,从意图识别到RAG知识增强,还分享技术人员AI改造系统指南与普通人把握AI时代机遇的方法。AI不是魔法,是超级工程学!文 / 勇哥&…

2025年口碑好的暗扣隐藏式家具拉手厂家实力及用户口碑排行榜

2025年口碑好的暗扣隐藏式家具拉手厂家实力及用户口碑排行榜 随着现代家居设计越来越注重简约与整体性,暗扣隐藏式家具拉手因其低调、美观、实用的特点,成为高端定制家具的首选配件。2025年,市场上涌现出众多优秀的…

Modern newspapers

Modern American newspapers are defintely not by A.I.(ai) Because the errors are just too much. Not to mention physics and mathematics, many journalists may EVEN have problems with geography and literat…

2025新一代公众号编辑器,有一云AI以绝对优势拔得头筹

2025新一代公众号编辑器,有一云AI以绝对优势拔得头筹在自媒体行业蓬勃发展的当下,创作者们面临着诸多挑战。从文章创作到排版配图,再到多平台分发,每一个环节都需要耗费大量的时间和精力。如何在激烈的竞争中脱颖而…

2025年二手航吊吨袋厂家推荐及选购参考榜

2025年二手航吊吨袋厂家推荐及选购参考榜行业概述在当今物流与工业运输领域,吨袋(又称集装袋)已成为大宗粉状、颗粒状物料运输不可或缺的包装工具。随着环保意识增强和资源循环利用理念普及,二手航吊吨袋市场近年来…

C++项目指定依赖路径

1. 背景 A、B 两个项目都依赖fmt,但是A依赖fmt8, B依赖fmt9。 系统中存在两个版本的fmt:apt安装的fmt8 .h头文件在/usr/include/fmt/下, .so库文件在./lib/x86_64-linux-gnu/libfmt.so.8 还有一个源码编译的fmt,源…

2025 年 10 月气缸管厂家推荐排行榜,精密气缸管,不锈钢气缸管,珩磨气缸管,薄壁气缸管,焊接气缸管,冷拔气缸管,食品级气缸管,海洋用气缸管公司推荐

2025年10月气缸管厂家推荐排行榜:精密气缸管、不锈钢气缸管等全品类专业解析 一、气缸管行业发展趋势与技术要求 气缸管作为工业自动化领域的核心零部件,其技术发展水平直接关系到整个制造业的升级进程。随着工业4.0…

2025年评价高的格栅机维修厂家推荐及采购参考

2025年评价高的格栅机维修厂家推荐及采购参考 在污水处理、环保工程等领域,格栅机作为预处理设备的核心部件,其性能与稳定性直接影响整体系统的运行效率。随着环保标准的不断提高,市场对高品质格栅机及维修服务的需…

2025年口碑好的中温伴热带厂家最新用户好评榜

2025年口碑好的中温伴热带厂家最新用户好评榜在工业保温和防冻领域,中温伴热带作为关键的热控解决方案,其性能和质量直接影响着生产安全和能源效率。随着2025年的到来,市场上涌现出一批技术领先、服务优质的伴热带生…

2025年10月卖得好的学习机品牌推荐:销量榜排行与可信评测

开学季刚过,家长群里最热的词就是“学习机”。不少父母白天上班,晚上陪娃写作业,发现课本难度升级、作业题型灵活,自己辅导力不从心;老人带娃的,更怕教错拼音、读错英语发音。于是,一台“能讲课、能批改、能同步…

2025 年 10 月三层绝缘线厂家推荐排行榜,东特/大亚/TOTOKU/古河/TIW-2/TIW-3/TIW-4/TIW-E/TIW-2S/TEX-E 三层绝缘线公司推荐

2025 年 10 月三层绝缘线厂家推荐排行榜,东特/大亚/TOTOKU/古河/TIW-2/TIW-3/TIW-4/TIW-E/TIW-2S/TEX-E 三层绝缘线公司推荐 行业背景分析 三层绝缘线作为电子元器件领域的关键材料,在电源适配器、变压器、新能源汽车…

2025年10月卖得好的学习机品牌推荐:销量榜对比指南

开学季刚过,家长群里的讨论热度却丝毫未减:孩子作业辅导时间被拉长,校外培训缩减,如何在家就能完成“精准补弱”成为多数家庭的共同焦虑。艾瑞咨询《2025家庭教育投入报告》显示,78.4%的中小学生家长计划年内购入…

[题解]G. Puzzle II - The 3rd Universal Cup. Stage 2: Zielona Gra

#8523. Puzzle II 四句话题意 给定两个长由黑白球组成的环,每个环有 \(n\) 个球,且黑球和白球的总数都是 \(n\)。 你可以进行最多 \(n\) 次操作,每次操作选定两个环上长度恰为 \(k\) 的区间交换。 最终要使两个环都…

2025年10月精华液推荐榜:淡斑提亮多效精华权威排名发布

在护肤步骤里,精华液因浓度高、分子小、作用深,被多数用户视为“见效加速器”。然而,真正到选购时,大家往往面临三重困扰:一是功效单一,买了美白款却忽略修护,结果屏障受损;二是刺激风险,成分“猛”但肤感刺痛…

2025年10月教育资源好的学习机品牌推荐:家长关注榜对比与实测排行

开学季刚过,家长群里“作业辅导崩溃”的吐槽却持续升温:课本同步难、题库更新慢、视频讲解找不到、孩子学一阵就腻。这些痛点背后,是“双减”后家庭对校内同步、精准提分、自主学习的刚性需求。教育部《2024全国教育…

2025年10月教育资源好的学习机品牌推荐:热门榜数据化评价

开学季刚过,不少家长发现孩子在家自学时依旧离不开“搜题—看视频—再做题”的循环,可手机平板内容杂、广告多,很难保证学习专注度;老师反馈课堂时间被新课标压缩,回家需要补充练习,却又担心家长辅导不到位。多重…

2025年10月性价比高的学习机品牌推荐:市场销量榜解析高价值学习方案

开学季刚过,家长群里的讨论热度却丝毫未减:怎样在预算有限的前提下,为孩子挑到一台“不闲置、真提分”的学习机?调研机构多鲸教育研究院2025年9月发布的《中国家庭教育硬件支出报告》显示,78%的家庭把“性价比”列…

2025年读书郎深度解析:26年教育科技长跑的硬实力与隐忧,

引言 本文聚焦“产品与技术”维度,对读书郎进行拆解,为家庭与学校选购智能学习设备提供一份可验证、可对照的客观参考。 背景与概况 读书郎教育科技成立于1999年,于2022年在港交所成功上市,是中国领先的智能学习设…

2025年读书郎深度解析:26年教育科技长跑的硬实力与隐忧。

引言 本文聚焦“市场表现”这一核心维度,以第三方可核查数据为经、行业交叉验证为纬,为家庭与学校选购教育硬件提供一份可落地的客观参考。 背景与概况 读书郎教育科技成立于1999年,于2022年在港交所成功上市,是中…