还在为高昂的AI开发成本发愁?这本书教你如何在个人电脑上引爆DeepSeek的澎湃算力!

Java 21 作为 Oracle JDK 的长期支持版本,引入了多项革命性特性,其中虚拟线程(Virtual Threads)和结构化并发(Structured Concurrency)尤为突出。这些特性旨在解决传统线程模型在高并发场景下的性能瓶颈和编程复杂性。虚拟线程通过轻量级线程实现,使得开发者可以轻松创建数百万个线程,而无需担心操作系统资源的消耗;结构化并发则提供了一种更安全、更易管理的并发编程范式,避免了线程泄漏和异常传播问题。本文将从历史背景出发,详细剖析虚拟线程的原理、API 使用和性能优化,结合大量代码示例和中文注释进行说明。同时,深入探讨结构化并发的核心概念、ScopedValue 和 StructuredTaskScope 等工具的使用场景。通过实际案例和对比分析,帮助读者理解这些新特性如何提升 Java 应用的并发能力,并探讨其在微服务、Web 服务器等领域的应用前景。文章强调实践导向,提供丰富的代码片段和解释,助力开发者快速上手 Java 21 的并发编程革命。总之,这些特性标志着 Java 在并发领域的重大进步,将为现代应用开发注入新活力。

引言:Java 并发编程的演进

Java 自 1995 年诞生以来,并发编程一直是其核心优势之一。从早期的 synchronized 关键字和 Thread 类,到 Java 5 引入的 java.util.concurrent 包(如 ExecutorService、Future 和 Lock),再到 Java 8 的 CompletableFuture 和 Stream API,Java 的并发模型不断演进。然而,随着云计算和大数据时代的到来,传统平台线程(Platform Threads)模型暴露出了诸多局限性:每个线程都需要操作系统内核的支持,导致创建和管理开销巨大;在高并发场景下,线程数受限于系统资源,容易引发 OutOfMemoryError 或上下文切换开销过高的问题。

Java 21(2023 年 9 月发布)作为 LTS(Long-Term Support)版本,引入了虚拟线程和结构化并发这两大特性,旨在从根本上革新并发编程。虚拟线程是 Project Loom 的成果,它将线程从操作系统内核中解耦,使用 JVM 内部的轻量级调度器管理,从而允许创建海量线程。结构化并发则通过新的 API(如 StructuredTaskScope)提供了一种结构化的任务管理方式,确保子任务的生命周期与父任务绑定,避免了传统多线程编程中的“野线程”问题。

本文将深入探讨这些特性。首先,我们将介绍虚拟线程的背景和原理,然后通过代码示例演示其使用。接着,详解结构化并发,并结合实际场景进行分析。为了便于理解,我们会提供大量带有中文注释的 Java 代码,并解释每个部分的实现逻辑。如果涉及性能建模,我们会使用 LaTeX 公式进行表示,例如线程切换开销的简化模型: T s w i t c h = α + β ⋅ N T_{switch} = \alpha + \beta \cdot N Tswitch=α+βN,其中 (\alpha) 是固定开销,(\beta) 是每个线程的额外成本,(N) 是线程数。

第一部分:虚拟线程的原理与实现

1.1 虚拟线程的背景

传统 Java 线程是基于操作系统线程的 1:1 映射模型,每个 Java 线程对应一个内核线程。这导致了几个问题:

  • 资源消耗高:内核线程需要栈空间(通常 1MB 以上)和调度资源,限制了线程总数(典型服务器上不超过几千个)。
  • 上下文切换开销:当线程阻塞(如 I/O 操作)时,内核需要保存和恢复上下文,消耗 CPU 时间。
  • 编程模型复杂:开发者往往使用线程池来复用线程,但这引入了异步编程的复杂性,如回调地狱或 Reactive Streams。

Project Loom 旨在引入 Go 语言式的 Goroutines 或 Kotlin 的 Coroutines 类似机制:虚拟线程(Virtual Threads)。虚拟线程是 JVM 管理的用户模式线程,与内核线程是 M:N 映射(多个虚拟线程映射到少量内核线程)。当虚拟线程阻塞时,JVM 可以将其“挂起”到堆上,而不阻塞内核线程,从而实现高效的并发。

在 Java 21 中,虚拟线程通过 Thread.ofVirtual() 创建,默认栈大小仅为传统线程的几分之一。性能测试显示,虚拟线程可以轻松处理数百万并发任务,而传统线程在数千个时就崩溃。

1.2 虚拟线程的 API 使用

虚拟线程的创建非常简单。以下是基本示例:

// 导入必要的包
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;public class VirtualThreadDemo {public static void main(String[] args) {// 创建虚拟线程工厂ThreadFactory virtualFactory = Thread.ofVirtual().factory();// 使用 Executors 创建执行器服务try (var executor = Executors.newThreadPerTaskExecutor(virtualFactory)) {// 提交 10000 个任务,每个任务模拟 I/O 操作for (int i = 0; i < 10000; i++) {final int taskId = i;executor.submit(() -> {try {// 模拟阻塞操作,如网络调用Thread.sleep(1000);System.out.println("任务 " + taskId + " 完成,由虚拟线程执行: " + Thread.currentThread().getName());} catch (InterruptedException e) {Thread.currentThread().interrupt();}});}} // executor 会自动关闭System.out.println("所有任务提交完成");}
}

在这个代码中,我们使用 Thread.ofVirtual().factory() 创建虚拟线程工厂,然后通过 Executors.newThreadPerTaskExecutor() 为每个任务创建一个新虚拟线程。注意,try-with-resources 确保 executor 关闭。每个任务使用 Thread.sleep() 模拟阻塞,这在虚拟线程中不会阻塞底层内核线程。

解释:传统线程池(如 Executors.newFixedThreadPool(10))会限制线程数为 10,导致任务排队。而在虚拟线程中,我们可以提交 10000 个任务,每个都有自己的线程,但实际内核线程只有少数几个(通常等于 CPU 核心数)。这大大提高了吞吐量。

1.3 虚拟线程的性能分析

虚拟线程的性能优势可以用数学模型表示。假设传统线程的上下文切换开销为 C t r a d = k ⋅ N C_{trad} = k \cdot N Ctrad=kN,其中 (k) 是常量,(N) 是线程数。对于虚拟线程,当阻塞时,开销接近零,因为 JVM 使用 continuation(延续)机制保存状态: C v i r t = m ⋅ P C_{virt} = m \cdot P Cvirt=mP,其中 (m < k),(P) 是活跃线程数(远小于 (N))。

以下代码演示性能对比:我们创建 100000 个线程,测量时间。

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.CountDownLatch;public class PerformanceCompare {public static void main(String[] args) throws InterruptedException {testVirtualThreads(100000);testPlatformThreads(100000); // 注意:这可能导致 OOM}private static void testVirtualThreads(int count) throws InterruptedException {Instant start = Instant.now();CountDownLatch latch = new CountDownLatch(count);ThreadFactory factory = Thread.ofVirtual().factory();for (int i = 0; i < count; i++) {Thread thread = factory.newThread(() -> {try {// 模拟工作Thread.

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

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

相关文章

Apache IoTDB 全场景部署:基于 Apache IoTDB 的跨「端-边-云」的时序数据库 DB+AI

Apache IoTDB 全场景部署&#xff1a;基于 Apache IoTDB 的跨「端-边-云」的时序数据库 DBAI 文章目录Apache IoTDB 全场景部署&#xff1a;基于 Apache IoTDB 的跨「端-边-云」的时序数据库 DBAIApache IoTDB 介绍Docker部署指导企业版数据库配套工具 WorkbenchTimechoDB&…

计算机网络---传输控制协议Transmission Control Protocol(TCP)

一、TCP的定位与核心特性 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是TCP/IP协议栈中传输层的核心协议&#xff0c;与UDP&#xff08;用户数据报协议&#xff09;共同承担端到端数据传输功能。其设计目标是在不可靠的IP网络上提供可靠…

week1-[分支嵌套]公因数

week1-[分支嵌套]公因数 题目描述 给定 444 个正整数 a,b,c,ka,b,c,ka,b,c,k。如果 a,b,ca,b,ca,b,c 都是 kkk 的倍数&#xff0c;那么称 kkk 是 a,b,ca,b,ca,b,c 的公因数。否则如果某两个数都是 kkk 的倍数&#xff0c;那么称 kkk 是这两个数的公因数。问 kkk 是哪些数的公因…

C#枚举/结构体讲一讲

先展示一段简单代码// 定义枚举 public enum thisday {吃饭,不吃 }// 定义结构体 public struct person {public string name;public int age;public thisday zhuangtai; // 使用枚举类型作为字段 }static void Main(string[] args) {// 创建结构体实例person thisperson;thisp…

C++-setmap详解

Cset&map 1. 序列式容器和关联式容器 1.1 序列式容器 序列式容器按照线性顺序存储元素&#xff0c;元素的位置取决于插入的时间和位置&#xff0c;与元素的值无关。 主要特点&#xff1a;元素按插入顺序存储可以通过位置&#xff08;索引&#xff09;直接访问元素不自动排序…

解决程序连不上RabbitMQ:Attempting to connect to/access to vhost虚拟主机挂了的排错与恢复

前言&#xff1a;在分布式系统里&#xff0c;RabbitMQ作为消息中间件&#xff0c;是服务间通信的关键纽带。但实际使用中&#xff0c;程序连接RabbitMQ失败的情况时有发生。本文结合真实报错&#xff0c;细致呈现从问题发现到解决的完整排错思路&#xff0c;还会深入讲解Rabbit…

K8S中如何配置PDB(Pod Disruption Budget)

1. PDB 核心概念作用&#xff1a;控制自愿中断&#xff08;如节点升级、缩容&#xff09;期间&#xff0c;应用的最小可用副本数或最大不可用比例。关键参数&#xff1a;minAvailable&#xff1a;必须保持运行的 Pod 数量&#xff08;如 2 或 50%&#xff09;。maxUnavailable&…

从 0 到 1:用 MyCat 打造可水平扩展的 MySQL 分库分表架构

一、为什么要分库分表&#xff1f; 单机 MySQL 的极限大致在&#xff1a;维度经验值单表行数≤ 1 000 万行&#xff08;B 树三层&#xff09;单库磁盘≤ 2 TB&#xff08;SSD&#xff09;单机 QPS≤ 1 万&#xff08;InnoDB&#xff09;当业务继续增长&#xff0c;数据量和并发…

电池模组奇异值分解降阶模型

了解如何将奇异值分解 (SVD) 降阶模型 (ROM) 应用于电池模块热模拟。挑战随着电池模块在电动汽车和储能系统中的重要性日益提升&#xff0c;其热性能管理也成为一项重大的工程挑战。高功率密度会产生大量热量&#xff0c;如果散热不当&#xff0c;可能导致电池性能下降、性能下…

《Python函数:从入门到精通,一文掌握函数编程精髓》

坚持用 清晰易懂的图解 代码语言&#xff0c;让每个知识点变得简单&#xff01; &#x1f680;呆头个人主页详情 &#x1f331; 呆头个人Gitee代码仓库 &#x1f4cc; 呆头详细专栏系列 座右铭&#xff1a; “不患无位&#xff0c;患所以立。” Python函数&#xff1a;从入门到…

【记录贴】STM32 I2C 控制 OLED 卡死?根源在 SR1 与 SR2 的读取操作

问题描述最近在复用以前STM32F407控制OLED的代码&#xff0c;移植到STM32F103 上&#xff0c;使用硬件 I2C 通信方式。按照常规流程&#xff0c;先发送 OLED 的从机地址&#xff0c;OLED 有正常应答&#xff0c;但当发送第一个控制命令&#xff08;0xAE&#xff09;前的控制字节…

【AI驱动的语义通信:突破比特传输的下一代通信范式】

文章目录1 语义通信简介1.1 基本概念&#xff1a;什么是语义通信&#xff1f;语义通信的核心目标1.2 基本结构&#xff1a;语义通信系统结构语义通信系统的通用结构组成语义通信系统的结构关键模块1.3 基于大模型的语义通信关键技术&#x1f9e0;语义通信系统中AI大模型的设计建…

网络原理-HTTP

应用层自定义协议自定义协议是指根据特定需求设计的通信规则&#xff0c;用于设备或系统间的数据交换。其核心在于定义数据结构、传输方式及处理逻辑。协议结构示例典型的自定义协议包含以下部分&#xff1a;头部&#xff08;Header&#xff09;&#xff1a;标识协议版本、数据…

ROS配置debug指南

一. 安装插件 下面的这一个插件过期了需要用下面的这一个插件来替换:二. 设置CMakeLists.txt的编译模式 set(CMAKE_BUILD_TYPE "Debug") set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAG…

微软正式将GPT-5接入Microsoft Copilot Studio(国际版)

微软宣布正式在Microsoft Copilot Studio&#xff08;国际版&#xff09;中集成GPT-5&#xff0c;推动智能体构建能力实现突破性升级。此次更新不仅为企业用户带来更高效的响应速度、更精准的语境理解能力&#xff0c;还通过增强的逻辑推理功能&#xff0c;显著提升了AI交互的深…

微算法科技(NASDAQ:MLGO)通过蚁群算法求解资源分配的全局最优解,实现低能耗的区块链资源分配

随着区块链网络规模的不断扩大和业务需求的日益复杂&#xff0c;资源分配问题逐渐成为制约其发展的关键因素之一。传统的区块链资源分配方法往往存在效率低下、能耗过高、难以达到全局最优解等问题。高能耗不仅增加了运营成本&#xff0c;还对环境造成了较大的压力。因此&#…

深入浅出JVM:Java虚拟机的探秘之旅

深入浅出JVM&#xff1a;Java虚拟机的探秘之旅一、JVM 初相识&#xff1a;揭开神秘面纱 在 Java 的世界里&#xff0c;JVM&#xff08;Java Virtual Machine&#xff0c;Java 虚拟机&#xff09;就像是一个神秘的幕后大 boss&#xff0c;掌控着 Java 程序运行的方方面面。你可以…

Nginx学习笔记(八)—— Nginx缓存集成

&#x1f5c4;&#x1f5c4; Nginx缓存集成 &#x1f4cc;&#x1f4cc; 一、缓存核心价值 #mermaid-svg-CNji1KUDOsF8MwoY {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-CNji1KUDOsF8MwoY .error-icon{fill:#5522…

httpx 设置速率控制 limit 时需要注意 timeout 包含 pool 中等待时间

假设通过 httpx.Client 设置 limit 速率控制后&#xff0c;同时发起多个请求访问 youtube。并且由于科学原因一直连接不上 假设一共 4 个连接&#xff0c;max_connection2&#xff0c;timeout5s。 默认会发生的情况不是前两个连接 tcp 握手 timeout&#xff0c;后两个连接再发起…

【网络】TCP/UDP总结复盘

1.UDP的格式2.TCP的格式3.TCP是来解决什么问题的&#xff1f;答&#xff1a;解决IP层的不可靠传输问题&#xff0c;可能数据包丢失、损坏、重复等为上层应用层提高可靠有序的数据传输服务通过校验和、确认应答机制、序列号来解决不可靠传输和无序性问题通过流量控制--->>…