SpringBoot3中使用虚拟线程的详细过程

news2026/2/26 14:14:17

在 Spring Boot 3 中使用 Java 21+ 的虚拟线程(Virtual Threads)可以显著提升 I/O 密集型应用的并发能力。以下是详细实现步骤:


1. 环境准备

  • JDK 21+:确保安装 JDK 21 或更高版本
  • Spring Boot 3.2+:最低要求(pom.xmlbuild.gradle
<!-- Maven 依赖 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version> <!-- 或更高版本 -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
// Gradle 依赖
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

2. 配置虚拟线程

方式一:全局启用虚拟线程(Tomcat/Jetty)

import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Executors;

@Configuration
public class VirtualThreadConfig {

    // Tomcat 配置(默认服务器)
    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> 
            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
    }

    // Jetty 配置(如使用Jetty)
    // @Bean
    // public JettyVirtualThreadsCustomizer jettyVirtualThreadsCustomizer() {
    //    return new JettyVirtualThreadsCustomizer();
    // }
}

方式二:异步任务使用虚拟线程

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean(name = "virtualThreadExecutor")
    public Executor virtualThreadExecutor() {
        return Thread.ofVirtual().name("virtual-", 0).factory()::newThread;
    }
}

使用异步方法:

@Service
public class AsyncService {

    @Async("virtualThreadExecutor")  // 指定执行器
    public CompletableFuture<String> asyncTask() {
        // 模拟耗时I/O操作
        return CompletableFuture.completedFuture("Virtual thread task completed");
    }
}

3. 验证虚拟线程

测试控制器

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;

@RestController
public class TestController {

    @GetMapping("/thread")
    public String getThreadType() {
        // 打印当前线程信息
        Thread thread = Thread.currentThread();
        return """
            Thread name: %s
            Is virtual: %s
            Platform thread: %s
            """.formatted(
                thread.getName(),
                thread.isVirtual(),
                thread.isVirtual() ? "N/A" : thread.toString()
            );
    }

    @GetMapping("/sleep")
    public CompletableFuture<String> sleep() throws InterruptedException {
        Thread.sleep(1000); // 模拟I/O阻塞
        return CompletableFuture.completedFuture(
            "Done by: " + Thread.currentThread().getName()
        );
    }
}

4. 启动应用

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

5. 测试验证

  1. 访问 http://localhost:8080/thread 查看线程类型:
    Thread name: virtual-0
    Is virtual: true
    Platform thread: N/A
    
  2. 并发测试(使用 ab 或 JMeter):
    ab -n 1000 -c 200 http://localhost:8080/sleep
    
    观察低内存占用和高吞吐量

关键注意事项

  1. 阻塞操作识别

    • 虚拟线程在 synchronized 块或本地方法调用时会固定到平台线程
    • 使用 jcmd <PID> Thread.dump_to_file -format=json <file> 分析线程状态
  2. 线程局部变量

    • 虚拟线程支持 ThreadLocal,但避免滥用(可能增加内存压力)
    • 考虑使用 ScopedValue(Java 21+)
  3. 数据库连接池

    // application.properties
    spring.datasource.hikari.thread-factory=java.util.concurrent.ThreadFactory
    
  4. 调试配置

    java -Djdk.tracePinnedThreads=full -jar your-app.jar
    

完整配置示例(Tomcat + HikariCP)

@Configuration
public class VirtualThreadGlobalConfig {

    // Tomcat 虚拟线程执行器
    @Bean
    TomcatProtocolHandlerCustomizer<?> tomcatVirtualThreads() {
        return handler -> handler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
    }

    // HikariCP 使用虚拟线程工厂
    @Bean
    @ConfigurationProperties("spring.datasource.hikari")
    public HikariDataSource dataSource() {
        return new HikariDataSource(new HikariConfig() {{
            setThreadFactory(Thread.ofVirtual().factory());
        }});
    }

    // 异步任务执行器
    @Bean
    Executor virtualThreadExecutor() {
        return Executors.newVirtualThreadPerTaskExecutor();
    }
}

重要提示:虚拟线程最适合 I/O 密集型场景(如网络请求、数据库调用),对计算密集型任务提升有限。生产环境务必进行压力测试!

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

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

相关文章

词法分析和词性标注 自然语言处理

目录 一. 概述 1 不同语言的词法分析 2 英语的形态分析 英语单词的形态还原&#xff08;和正常英语的词法变化一样&#xff09; 1.有规律变化单词的形态还原 ​编辑 2.动词&#xff64;名词&#xff64;形容词&#xff64;副词不规则变化单词的形态还原 3.对于表示年代&…

QT聊天项目DAY14

1. 客户端登录 1.1 初始化玩家头像 将头像的大小固定在250 * 250 void InitHeadImage(); // 初始化头像/* 初始化头像 */ void LoginWidget::InitHeadImage() {// 加载头像QPixmap OriginalPixmap(":/Chat/Images/head_5.jpg");OriginalPixmap …

架构设计技巧——架构设计模板

一份实用、高效、覆盖核心要素的架构设计模板是确保设计质量、促进团队沟通和指导实施的关键。以下是一个经过提炼的架构设计文档核心模板框架&#xff0c;结合了业界最佳实践&#xff0c;并强调灵活裁剪&#xff1a; 架构设计文档模板 (核心框架) 文档标识 项目/系统名称&a…

【Ragflow】27.RagflowPlus(v0.4.1):小版本迭代,问题修复与功能优化

概述 RagflowPlus v0.4.0 在发布后&#xff0c;收到了积极的反馈&#xff0c;同时也包含一些问题。 本次进行一轮小版本更新&#xff0c;发布 v0.4.1 版本&#xff0c;对已知问题进行修复&#xff0c;并对部分功能进行进一步优化。 开源地址&#xff1a;https://github.com/…

【Oracle】数据仓库

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 数据仓库概述1.1 为什么需要数据仓库1.2 Oracle数据仓库架构1.3 Oracle数据仓库关键技术 2. 数据仓库建模2.1 维度建模基础2.2 星形模式设计2.3 雪花模式设计2.4 缓慢变化维度&#xff08;SCD&#xff09;处…

基于开源AI大模型AI智能名片S2B2C商城小程序源码的中等平台型社交电商运营模式研究

摘要&#xff1a;本文聚焦中等平台型社交电商&#xff0c;探讨其与传统微商及大型社交电商平台的差异&#xff0c;尤其关注产品品类管理对代理运营的影响。通过引入开源AI大模型、AI智能名片与S2B2C商城小程序源码技术&#xff0c;构建智能化运营体系。研究结果表明&#xff0c…

Vite 双引擎架构 —— Esbuild 概念篇

Vite 底层采用 双引擎架构&#xff0c;核心构建引擎是 Esbuild 和 Rollup&#xff0c;二者在开发和生产环境中分工协作&#xff0c;共同实现高性能构建。不可否认&#xff0c;作为 Vite 的双引擎之一&#xff0c;Esbuild 在很多关键的构建阶段(如依赖预编译、TS 语法转译、代码…

阿里云Alibaba Cloud安装Docker与Docker compose【图文教程】

个人记录 进入控制台&#xff0c;找到定时与自动化任务 进入‘安装/卸载扩展程序’ 点击‘安装扩展程序’ 选择docker社区版&#xff0c;点击下一步与确定&#xff0c;等待一会 安装成功 查询版本 查询docker sudo docker version查询docker compose sudo docker compo…

ADB识别手机系统弹授权框-如何处理多重弹框叠加和重叠问题

ADB识别手机系统弹授权框-如何处理多重弹框叠加和重叠问题 --蓝牙电话SDK自动部署 上一篇&#xff1a;手机App-插入USB时自动授权点击确定按钮-使系统弹出框自动消失 下一篇&#xff1a;编写中。 一、前言 我们在上一篇《手机App-插入USB时自动授权点击确定按钮-使系统弹出框…

uniapp+<script setup lang=“ts“>解决有数据与暂无数据切换显示,有数据加载时暂无数据闪现(先加载空数据)问题

声明showEmpty 为false&#xff0c;在接口返回处判断有数据时设置showEmpty 为false&#xff0c;接口返回数据为空则判断showEmpty 为true &#xff08;这样就解决有数据的时候会闪现暂无数据的问题啦&#xff09; <!--* Date: 2024-02-26 03:38:52* LastEditTime: 2025-06…

详解鸿蒙Next仓颉开发语言中的动画

大家上午好&#xff0c;今天来聊一聊仓颉开发语言中的动画开发。 仓颉中的动画通常有两种方式&#xff0c;分别是属性动画和显示动画&#xff0c;我们今天以下面的加载动画为例&#xff0c;使用显示动画和属性动画分别实现一下&#xff0c;看看他们有什么区别。 显示动画 显示…

Redis常见使用场景解析

1. 数据库缓存 Redis 作为典型的 Key-Value 型内存数据库,数据缓存是其最广为人知的应用场景。使用 Redis 缓存数据操作简便,通常将序列化后的对象以 string 类型存储。但在实际应用中,需注意以下关键要点: Key 设计:必须确保不同对象的 Key 具有唯一性,且尽量缩短长度,…

起重机指挥人员在工作中需要注意哪些安全事项?

起重机指挥人员在作业中承担着协调设备运行、保障作业安全的关键职责&#xff0c;其安全操作直接关系到整个起重作业的安全性。以下从作业前、作业中、作业后的全流程&#xff0c;详细说明指挥人员需注意的安全事项&#xff1a; 一、作业前的安全准备 资质与状态检查&#xff…

JAVA-springboot log日志

SpringBoot从入门到精通-第8章 日志的操作 一、Spring Boot默认的日志框架 SpringBoot支持很多种日志框架&#xff0c;通常情况下&#xff0c;这些日志框架都是由一个日志抽象层和一个日志实现层搭建而成的&#xff0c;日志抽象层是为记录日志提供的一套标准且规范的框架&…

1.springmvc基础入门(一)

1.Spring MVC概念 Spring MVC 是 Spring Framework 提供的 Web 组件&#xff0c;全称是 Spring Web MVC&#xff0c;是⽬前主流的实现 MVC 设计模式的框架&#xff0c;提供前端路由映射、视图解析等功能。 Java Web 开发者必须要掌握的技术框架。 2.Spring MVC 功能 MVC&am…

模块缝合-把A模块换成B模块(没写完)

把MLP Head替换为KAN 1.在model文件下新建一个python文件 2.把 模块文件里的整个KAN代码复制到新的python文件中 3.在开头导入 from model.KAN(新建文件名&#xff09; import KAN&#xff08;新建文件中的类名&#xff09; 4.sys.path.append(r"D: Icode(Kansformer"…

从零开始学Flink:揭开实时计算的神秘面纱

一、为什么需要Flink&#xff1f; 当你在电商平台秒杀商品时&#xff0c;1毫秒的延迟可能导致交易失败&#xff1b;当自动驾驶汽车遇到障碍物时&#xff0c;10毫秒的计算延迟可能酿成事故。这些场景揭示了一个残酷事实&#xff1a;数据的价值随时间呈指数级衰减。 传统批处理…

Appium如何支持ios真机测试

ios模拟器上UI自动化测试 以appiumwebdriverio为例&#xff0c;详细介绍如何在模拟器上安装和测试app。在使用ios模拟器前&#xff0c;需要安装xcode&#xff0c;创建和启动一个simulator。simulator创建好后&#xff0c;就可以使用xcrun simctl命令安装被测应用并开始测试了。…

JDK17 Http Request 异步处理 源码刨析

为什么可以异步&#xff1f; #调用起始源码 // 3. 发送异步请求并处理响应 CompletableFuture future client.sendAsync( request, HttpResponse.BodyHandlers.ofString() // 响应体转为字符串 ).thenApply(response -> { // 状态码检查&#xff08;非200系列抛出异常&…

【Zephyr 系列 8】构建完整 BLE 产品架构:状态机 + AT 命令 + 双通道通信实战

🧠关键词:Zephyr、BLE、状态机、双向透传、AT 命令、Buffer、主从共存、系统架构 📌适合人群:希望开发 BLE 产品(模块/标签/终端)具备可控、可测、可维护架构的开发者 🧭 引言:从“点功能”到“系统架构” 前面几篇我们已经逐步构建了 BLE 广播、连接、数据透传系统…