Spring Boot 3.2.0 虚拟线程初体验 (部分装配解析)

news2024/11/19 13:44:21

写在前面

  • spring boot 3 已经提供了对虚拟线程的支持。

  • 虚拟线程和平台线程主要区别在于,虚拟线程在运行周期内不依赖操作系统线程:它们与硬件脱钩,因此被称为 “虚拟”。这种解耦是由 JVM 提供的抽象层赋予的。

  • 虚拟线程的运行成本远低于平台线程。消耗的内存要少得多。这就是为什么可以创建数百万个虚拟线程而不会出现内存不足的问题,而标准平台(或内核)线程只能创建数百个。

  • 虚拟线程会优先使用JVM提供,如果不能使用JVM提供,则考虑使用由平台线程支持的“虚拟线程” ,相关源代码参考java.lang.ThreadBuilders#newVirtualThread

版本要求

  • spring boot 3.2.0
  • jdk 21

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>net.jlxxw</groupId>
    <artifactId>boot3-demo</artifactId>
    <version>1.0.0.20231128</version>
    <name>boot3-demo</name>
    <description>boot3-demo</description>
    <properties>
        <java.version>21</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>3.2.0</spring-boot.version>
    </properties>
    <dependencies>
       
        <dependency>
            <groupId>org.apache.httpcomponents.client5</groupId>
            <artifactId>httpclient5-fluent</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
   
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
                <configuration>
                    <!-- imageName用于设置生成的二进制文件名称 -->
                    <imageName>${project.artifactId}</imageName>
                    <!-- mainClass用于指定main方法类路径 -->

                    <!--                                <buildArgs>-->
                    <!--                                    no-fallback-->
                    <!--                                </buildArgs>-->
                </configuration>
<!--                <executions>-->
<!--                    <execution>-->
<!--                        <id>build-native</id>-->
<!--                        <goals>-->
<!--                            <goal>compile-no-fork</goal>-->
<!--                        </goals>-->
<!--                        <phase>package</phase>-->
<!--                    </execution>-->
<!--                </executions>-->
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

yml

spring:
  #启动虚拟线程的必须配置
  threads:
    virtual:
      # 启用虚拟线程技术,增加系统并发能力
      enabled: true

自动装配解析

Tomcat 虚拟线程自动配置类

org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration.TomcatWebServerFactoryCustomizerConfiguration#tomcatVirtualThreadsProtocolHandlerCustomizer

/*
 * Copyright 2012-2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure.web.embedded;

import io.undertow.Undertow;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.UpgradeProtocol;
import org.eclipse.jetty.ee10.webapp.WebAppContext;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Loader;
import org.xnio.SslClientAuthMode;
import reactor.netty.http.server.HttpServer;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment;
import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.thread.Threading;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

/**
 * {@link EnableAutoConfiguration Auto-configuration} for embedded servlet and reactive
 * web servers customizations.
 *
 * @author Phillip Webb
 * @since 2.0.0
 */
@AutoConfiguration
@ConditionalOnNotWarDeployment
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {

	/**
	 * Nested configuration if Tomcat is being used.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
	public static class TomcatWebServerFactoryCustomizerConfiguration {

		@Bean
		public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment,
				ServerProperties serverProperties) {
			return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
		}

		@Bean
		@ConditionalOnThreading(Threading.VIRTUAL)
		TomcatVirtualThreadsWebServerFactoryCustomizer tomcatVirtualThreadsProtocolHandlerCustomizer() {
			return new TomcatVirtualThreadsWebServerFactoryCustomizer();
		}

	}

	/**
	 * Nested configuration if Jetty is being used.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
	public static class JettyWebServerFactoryCustomizerConfiguration {

		@Bean
		public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(Environment environment,
				ServerProperties serverProperties) {
			return new JettyWebServerFactoryCustomizer(environment, serverProperties);
		}

		@Bean
		@ConditionalOnThreading(Threading.VIRTUAL)
		JettyVirtualThreadsWebServerFactoryCustomizer jettyVirtualThreadsWebServerFactoryCustomizer(
				ServerProperties serverProperties) {
			return new JettyVirtualThreadsWebServerFactoryCustomizer(serverProperties);
		}

	}

	/**
	 * Nested configuration if Undertow is being used.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass({ Undertow.class, SslClientAuthMode.class })
	public static class UndertowWebServerFactoryCustomizerConfiguration {

		@Bean
		public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(Environment environment,
				ServerProperties serverProperties) {
			return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
		}

	}

	/**
	 * Nested configuration if Netty is being used.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(HttpServer.class)
	public static class NettyWebServerFactoryCustomizerConfiguration {

		@Bean
		public NettyWebServerFactoryCustomizer nettyWebServerFactoryCustomizer(Environment environment,
				ServerProperties serverProperties) {
			return new NettyWebServerFactoryCustomizer(environment, serverProperties);
		}

	}

}

在这里插入图片描述

Tomcat虚拟线程定制器

org.springframework.boot.autoconfigure.web.embedded.TomcatVirtualThreadsWebServerFactoryCustomizer

/*
 * Copyright 2012-2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure.web.embedded;

import org.apache.coyote.ProtocolHandler;
import org.apache.tomcat.util.threads.VirtualThreadExecutor;

import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.core.Ordered;

/**
 * Activates {@link VirtualThreadExecutor} on {@link ProtocolHandler Tomcat's protocol
 * handler}.
 *
 * @author Moritz Halbritter
 * @since 3.2.0
 */
public class TomcatVirtualThreadsWebServerFactoryCustomizer
		implements WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory>, Ordered {

	@Override
	public void customize(ConfigurableTomcatWebServerFactory factory) {
		factory.addProtocolHandlerCustomizers(
				(protocolHandler) -> protocolHandler.setExecutor(new VirtualThreadExecutor("tomcat-handler-")));
	}

	@Override
	public int getOrder() {
		return TomcatWebServerFactoryCustomizer.ORDER + 1;
	}

}

新的虚拟线程池

org.apache.tomcat.util.threads.VirtualThreadExecutor

/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.apache.tomcat.util.threads;

import java.util.concurrent.Executor;

import org.apache.tomcat.util.compat.JreCompat;

/**
 * An executor that uses a new virtual thread for each task.
 */
public class VirtualThreadExecutor implements Executor {

    private final JreCompat jreCompat = JreCompat.getInstance();

    private Object threadBuilder;

    public VirtualThreadExecutor(String namePrefix) {
        threadBuilder = jreCompat.createVirtualThreadBuilder(namePrefix);
    }

    @Override
    public void execute(Runnable command) {
        jreCompat.threadBuilderStart(threadBuilder, command);
    }
}

测试对比效果

启用虚拟线程

在这里插入图片描述

未启用虚拟线程

在这里插入图片描述

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

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

相关文章

Android Bitmap保存成至手机图片文件,Kotlin

Android Bitmap保存成至手机图片文件&#xff0c;Kotlin fun saveBitmap(name: String?, bm: Bitmap) {val savePath Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()if (!Files.exists(Paths.get(savePath))) {Log.d("保存文…

Linux以nohup方式运行jar包

1、在需要运行的jar包同级目录下建立启动脚本文件&#xff1a; 文件内容&#xff1a; #! /bin/bash #注意&#xff1a;必须有&让其后台执行&#xff0c;否则没有pid生成 jar包路径为绝对路径 nohup java -jar /usr/local/testDemo/jdkDemo-0.0.1-SNAPSHOT.jar >/us…

计算机基础知识60

MySQL分组 # 概念&#xff1a;分组是按照某个指定的条件将单个单个的个体分成一个个整体 # MySQL分组的关键字&#xff1a;group by # 分组一般配合聚合函数使用&#xff1a; sum max min avg count 基本的语法格式: group by 字段名 [having 条件表达式] # 单独使用 group by关…

机器学习与低代码:简化AI开发的未来

机器学习&#xff08;Machine Learning&#xff09;的应用如火如荼地扩展&#xff0c;其影响力和潜力在各行业得到了充分展现。然而&#xff0c;对于广大开发者和企业来说&#xff0c;机器学习模型的构建和部署并非易事&#xff0c;其中涉及的复杂过程和专业知识往往令人望而却…

苍穹外卖项目笔记(6)— Redis操作营业状态设置

1 在 Java 中操作 Redis 1.1 Redis 的 Java 客户端 Jedis&#xff08;官方推荐&#xff0c;且命令语句同 redis 命令&#xff09;Lettuce&#xff08;底层基于 Netty 多线程框架实现&#xff0c;性能高效&#xff09;Spring Data Redis&#xff08;对 Jedis 和 Lettuce 进行了…

深入理解强化学习——马尔可夫决策过程:备份图(Backup Diagram)

分类目录&#xff1a;《深入理解强化学习》总目录 在本文中&#xff0c;我们将介绍备份&#xff08;Backup&#xff09;的概念。备份类似于自举之间的迭代关系&#xff0c;对于某一个状态&#xff0c;它的当前价值是与它的未来价值线性相关的。 我们将与下图类似的图称为备份图…

HassOS使用nmcli设置静态IPv4地址及网关、DNS

目录 显示hass在使用的默认连接显示此连接的所有配置编辑hass默认连接添加静态IP地址添加DNS和网关删除DNS查看IPv4属性保存配置并退出nmcli重载配置 首先控制台登陆Home Assistant OS Welcome to Home Assistant homeassistant login:使用root用户登录&#xff08;无需密码&a…

Linux基础项目开发1:量产工具——显示系统(二)

前言&#xff1a; 前面我们已经对这个项目的基本框架有了一个初步的了解与认识&#xff0c;要实现显示管理器与输入管理器&#xff0c;有输入有输出基本就实现这个项目的大部分功能了&#xff0c;首先我们先来做显示系统&#xff0c;对于上层系统为了让程序更好扩展&#xff0c…

MySQL--日志

日志 错误日志 错误日志是MySQL中最重要的日志之一&#xff0c;它记录了当mysqld启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息 当数据库出现任何故障导致无法正常使用时&#xff0c;建议首先查看此日志。 该日志是默认开启的&#xff0c;默认…

Mysql 高级日志binlog、undoLog、redoLog 详解

数据更新流程与日志记录&#xff1a; undoLog&#xff1a; binLog&#xff1a; redoLog&#xff1a;

计算机毕业设计php+bootstrap小区物业管理系统

意义&#xff1a;随着我国经济的发展和人们生活水平的提高&#xff0c;住宅小区已经成为人们居住的主流&#xff0c;人们生活质量提高的同时&#xff0c;对小区物业管理的要求也越来越高&#xff0c;诸如对小区的维修维护&#xff0c;甚至对各项投诉都要求小区管理者做得好&…

INFINI Gateway 与华为鲲鹏完成产品兼容互认证

何为华为鲲鹏认证 华为鲲鹏认证是华为云围绕鲲鹏云服务&#xff08;含公有云、私有云、混合云、桌面云&#xff09;推出的一项合作伙伴计划&#xff0c;旨在为构建持续发展、合作共赢的鲲鹏生态圈&#xff0c;通过整合华为的技术、品牌资源&#xff0c;与合作伙伴共享商机和利…

SpringBoot——模板引擎及原理

优质博文&#xff1a;IT-BLOG-CN 一、模板引擎的思想 模板是为了将显示与数据分离&#xff0c;模板技术多种多样&#xff0c;但其本质都是将模板文件和数据通过模板引擎生成最终的HTML代码。 二、SpringBoot模板引擎 SpringBoot推荐的模板引擎是Thymeleaf语法简单&#xff0…

堆排序(详解)

在上篇文章中&#xff0c;我们说利用堆的插入和删除也可以排序数据&#xff0c;但排序的只是堆里面的数组&#xff1b;同时每次排序数据都要单独写一个堆的实现&#xff0c;很不方便&#xff0c;这次就来着重讲讲如何使用堆排序。 1.建堆 给了你数据&#xff0c;要利用堆对数据…

MIGO收货报替代“ZF002“, 步骤““ 中存在语法错误消息号 GB032错误

MIGO收货报替代"ZF002", 步骤"" 中存在语法错误消息号 GB032错误。替代"ZF002", 步骤"" 中存在语法错误消息号 GB032诊断 在 ABAP 代码生成过程中&#xff0c;在替代ZF002中发现了语法错误。 系统响应 未为该布尔陈述生成 ABAP 代码&…

nodejs之express学习(1)

安装 npm i express使用 // 导入 const express require(express) // 创建应用 const app express() // 创建路由 app.get(/home,(req,res)>{res.end("hello express") }) app.listen(3000,()>{console.log("服务已启动~") })路由的介绍 什么是…

P9231 [蓝桥杯 2023 省 A] 平方差(拆分问题)

分析&#xff1a;x(yz)*(y-z); yz 与 y-z 同奇偶性&#xff08;x要么为奇数&#xff0c;要么为偶数&#xff09; 奇数&#xff1a;1 与 其本身 乘积 偶数&#xff1a;2 与 x/2 乘积(为4的倍数) #include<bit…

【shell】多行重定向与免交互expect与ssh、scp的结合使用

目录 一、多行重定向 举例1&#xff1a;使用read命令接收用户的输入值会有交互过程 举例2&#xff1a;设置变量的值 举例3&#xff1a;创建用户密码 举例4&#xff1a;使用多行重定向写入文件中&#xff08;以repo文件举例&#xff09; 举例5&#xff1a;变量设定 二、免…

C/C++ 发送与接收HTTP/S请求

HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于传输超文本的协议。它是一种无状态的、应用层的协议&#xff0c;用于在计算机之间传输超文本文档&#xff0c;通常在 Web 浏览器和 Web 服务器之间进行数据通信。HTTP 是由互联网工程任务组&#xff08;IETF…

java编程强化练习(一)

1. 素数因子数字和 【问题描述】从键盘终端输入一个正的整数&#xff0c;求其所有素数因子各位上数字之和。例如&#xff1a;442*2*11&#xff0c;素数因子为2&#xff0c;2&#xff0c;11&#xff0c;和为22114 【输入形式】一个正的整数 【输出形式】整数的所有素数因子各位…