Spring Boot 中的虚拟线程

在本文中,我将讨论 Spring Boot 中的虚拟线程。

在这里插入图片描述

什么是虚拟线程?

虚拟线程作为 Java 中的一项功能引入,旨在简化并发性。 Virtual threads 是 轻量级的线程,由 Java Virtual Machine 而不是操作系统管理。它们被设计为易于使用且高效,为并发编程提供了比传统 Java 线程更简单的模型。

在这里插入图片描述

  • Lightweight :与传统线程相比,虚拟线程的重量更轻。它们由 JVM 管理,许多虚拟线程可以映射到较少数量的操作系统线程。
  • Concurrency :虚拟线程旨在通过更轻松地编写可扩展和响应式应用程序来简化并发编程。
  • Thread Pool :不需要显式管理线程池。 JVM 可以根据工作负载动态调整线程数量。

在这里插入图片描述

没有执行器的虚拟线程声明方式

public static void main(String[] args) {Thread virtualThread = Thread.ofVirtual().start(() -> {System.out.println("Virtual thread running");});System.out.println("Main thread running");    }
private static void main(String[] args) {Thread virtualThread = Thread.ofVirtual().name("Virtual Thread").unstarted(() ->System.out.println("Virtual thread running"));t.start();try {virtualThread.join();} catch (InterruptedException e) {e.printStackTrace();}}

Spring Boot 中的实现

Java Version: 20
Spring Version: 3.1.0

1) pom.xml

 <dependencies><!--Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--Prometheus, Zipkin & Micrometer--><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId><scope>runtime</scope><version>1.11.0</version></dependency><dependency><groupId>io.zipkin.reporter2</groupId><artifactId>zipkin-reporter-brave</artifactId><version>2.16.3</version></dependency><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-tracing-bridge-brave</artifactId></dependency><!--Actuator & AOP--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId><version>3.1.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>20</source><target>20</target><compilerArgs>--enable-preview</compilerArgs></configuration></plugin></plugins>
</build>

必须确保有 Java 21 的 JVM 可用! (如果您运行的是 Java 19,则可以使用 --preview-enabled=true 运行虚拟线程。)

2) application.properties

spring.application.name=spring-vthread-servicemanagement.zipkin.tracing.endpoint=http://${ZIPKIN_HOST:localhost}:9411/api/v2/spans
management.tracing.sampling.probability=1.0
management.endpoints.web.exposure.include=info,health,prometheus,metrics
server.tomcat.mbeanregistry.enabled=true
management.metrics.tags.application=${spring.application.name}logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]

3)VThreadServiceApplication

1、创建100_000个传统Java线程并执行。
@SpringBootApplication
public class VThreadServiceApplication {public static void main(String[] args) {SpringApplication.run(VThreadServiceApplication.class, args);}@Beanpublic ApplicationRunner runner() {return args -> {var startDate = Instant.now();startThreads();var finishDate = Instant.now();System.out.println(String.format("Start Date: %s, Finish Date: %s", startDate, finishDate));System.out.println(String.format("Duration Time(Milliseconds): %s", Duration.between(startDate, finishDate).toMillis()));};}private void startThreads() throws InterruptedException {for (int i = 0; i < 100_000; i++) {int finalI = i;Thread t = new Thread(() -> System.out.println(finalI));t.start();t.join();}}}

输出:

 ..
99998
99999
Start Date: 2023-11-18T12:20:09.491114200Z, Finish Date: 2023-11-18T12:20:28.139291800Z
Duration Time(Milliseconds): 18648

Duration Time(Milliseconds): 18648

CPU使用率:

在这里插入图片描述

2.、创建100_000个虚拟Java线程并执行。

@SpringBootApplication
public class VThreadServiceApplication {public static void main(String[] args) {SpringApplication.run(VThreadServiceApplication.class, args);}@Beanpublic ApplicationRunner runner() {return args -> {var startDate = Instant.now();startVirtualThreads();var finishDate = Instant.now();System.out.println(String.format("Start Date: %s, Finish Date: %s", startDate, finishDate));System.out.println(String.format("Duration Time(Milliseconds): %s", Duration.between(startDate, finishDate).toMillis()));};}private void startVirtualThreads() throws InterruptedException {for (int i = 0; i < 100_000; i++) {int finalI = i;Thread t = Thread.ofVirtual().name(String.format("virtualThread-%s", i)).unstarted(() -> System.out.println(finalI));t.start();t.join();}}}

输出:

..
99998
99999
Start Date: 2023-11-18T12:22:14.838308900Z, Finish Date: 2023-11-18T12:22:18.588181800Z
Duration Time(Milliseconds): 3749

Duration Time(Milliseconds): 3749

CPU使用率:

在这里插入图片描述

3. 创建Http控制器
@RestController
@RequestMapping("/api/v1/threads")
@Slf4j
public class ThreadController {@GetMapping("")public String thread() throws InterruptedException {Thread.sleep(1000);var threadName = Thread.currentThread().toString();log.info(threadName);return "thread executed";}}
3.1 发送HTTP请求(传统线程)

发送 1600 请求。
并发请求数:400

命令

ab -n 1600 -c 400 host.docker.internal:8080/api/v1/threads

Response Summary

This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking host.docker.internal (be patient)
Completed 160 requests
Completed 320 requests
Completed 480 requests
Completed 640 requests
Completed 800 requests
Completed 960 requests
Completed 1120 requests
Completed 1280 requests
Completed 1440 requests
Completed 1600 requests
Finished 1600 requestsServer Software:
Server Hostname:        host.docker.internal
Server Port:            8080Document Path:          /api/v1/threads
Document Length:        15 bytesConcurrency Level:      400
Time taken for tests:   9.659 seconds
Complete requests:      1600
Failed requests:        0
Total transferred:      236800 bytes
HTML transferred:       24000 bytes
Requests per second:    165.65 [#/sec] (mean)
Time per request:       2414.722 [ms] (mean)
Time per request:       6.037 [ms] (mean, across all concurrent requests)
Transfer rate:          23.94 [Kbytes/sec] receivedConnection Times (ms)min  mean[+/-sd] median   max
Connect:        2  127  51.4    118     375
Processing:  1040 1877 258.2   1905    2438
Waiting:     1010 1755 257.0   1781    2304
Total:       1042 2004 268.9   2019    2660Percentage of the requests served within a certain time (ms)50%   201966%   203275%   204180%   204890%   254095%   260398%   263899%   2650100%   2660 (longest request)

Time taken for tests :9.659 秒

3.2发送HTTP请求(虚拟线程)

创建线程执行器
线程执行器配置

@Configuration
@Slf4j
public class ThreadExecutorConfig {@Beanpublic TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {return protocolHandler -> {log.info("Configuring " + protocolHandler + " to use VirtualThreadPerTaskExecutor");protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());};}}

发送 1600 请求。
并发请求数:400

Command 命令

ab -n 1600 -c 400 host.docker.internal:8080/api/v1/threads

Response Summary

This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking host.docker.internal (be patient)
Completed 160 requests
Completed 320 requests
Completed 480 requests
Completed 640 requests
Completed 800 requests
Completed 960 requests
Completed 1120 requests
Completed 1280 requests
Completed 1440 requests
Completed 1600 requests
Finished 1600 requestsServer Software:
Server Hostname:        host.docker.internal
Server Port:            8080Document Path:          /api/v1/threads
Document Length:        0 bytesConcurrency Level:      400
Time taken for tests:   7.912 seconds
Complete requests:      1600
Failed requests:        0
Total transferred:      211200 bytes
HTML transferred:       0 bytes
Requests per second:    202.22 [#/sec] (mean)
Time per request:       1978.077 [ms] (mean)
Time per request:       4.945 [ms] (mean, across all concurrent requests)
Transfer rate:          26.07 [Kbytes/sec] receivedConnection Times (ms)min  mean[+/-sd] median   max
Connect:        1  186  89.6    197     337
Processing:  1005 1376 251.1   1423    1855
Waiting:     1005 1198 158.2   1171    1591
Total:       1040 1562 244.2   1612    2060Percentage of the requests served within a certain time (ms)50%   161266%   166875%   169180%   172490%   190395%   199798%   203799%   2048100%   2060 (longest request)

Time taken for tests :7.912 秒

相关文档:

  • 三 分钟理解 Java 虚拟线程

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

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

相关文章

npm run dev 生成network网址无法被同局域网下的其他主机访问

当使用 npm run dev 运行开发服务器时&#xff0c;通常该服务器只会监听本地主机&#xff08;localhost&#xff09;&#xff0c;这意味着只有在运行服务器的计算机上可以访问。如果你希望其他主机也能够访问该开发服务器&#xff0c;你可能需要配置服务器以监听所有可用的网络…

知识付费小程序如何搭建?

随着互联网的发展和人们对知识的渴求&#xff0c;知识付费行业正逐渐崭露头角。而其中&#xff0c;知识付费小程序因其便捷性、个性化等特点&#xff0c;成为了越来越多人的首选。那么&#xff0c;如何搭建一个知识付费小程序呢&#xff1f;本文将为你揭秘从零到一的全过程&…

for参数 命令语句 变量

for 参数f skip命令语句 命令说明&#xff1a; 跳过文本内容&#xff08;行&#xff09;&#xff1a;skip 例子&#xff1a; for /f "skip1" %%i in(2.txt) do echo %%i for 参数f eol命令语句 命令说明&#xff1a; 怱略指定字符的文本内容&#xff08;文本首部…

ElasticSearch:centos7安装elasticsearch7,kibana,ik中文分词器,云服务器安装elasticsearch

系统&#xff1a;centos7 elasticsearch: 7.17.16 安装目录&#xff1a;/usr/local 云服务器的安全组&#xff1a;开放 9200 和5601的端口 一、下载安装elasticsearch7.17.16 1、安装 #进入安装目录 cd /usr/local#下载elasticsearch wget https://artifacts.elastic.co/d…

Elasticsearch:在不停机的情况下优化 Elasticsearch Reindex

实现零停机、高效率和成功迁移更新的指南。更多阅读&#xff1a;Elasticsearch&#xff1a;如何轻松安全地对实时 Elasticsearch 索引 reindex 你的数据。 在使用 Elasticsearch 的时候&#xff0c;总会有需要修改索引映射的时候&#xff0c;遇到这种情况&#xff0c;我们只能做…

前端实现websocket类封装

随着Web应用程序的发展&#xff0c;越来越多的人开始利用Websocket技术来构建实时应用程序。Websocket是一种在客户端和服务器之间建立持久连接的协议。这种协议可以在一个单独的连接上实现双向通信。与HTTP请求-响应模型不同&#xff0c;Websocket允许服务器自主地向客户端发送…

想要学会JVM调优,先掌握JVM内存模型和JVM运行原理

1、前言 今天将和你一起探讨Java虚拟机&#xff08;JVM&#xff09;的性能调优。 JVM算是面试中的高频问题了&#xff0c;通常情况下总会有人问到&#xff1a;请你讲解下 JVM 的内存模型&#xff0c;JVM 的 性能调优做过&#xff1f; 2、为什么 JVM 在 Java 中如此重要 首…

ansible加密

本章主要介绍如何对ansible中的playbook 进行加密。 对整个playbook进行加密查看加密文件运行加密的playbook对playbook进行解密使用密码文件对单个字符串进行加密 前面写了许多playbook&#xff0c;这些playbook都是以明文的方式存在的&#xff0c;有时想对这些 playbook进…

利用网络教育系统构建个性化学习平台

在现代教育中&#xff0c;网络教育系统作为一种创新的学习方式&#xff0c;为学生提供了更加个性化和灵活的学习体验。在本文中&#xff0c;我们将通过简单的技术代码&#xff0c;演示如何构建一个基础的网络教育系统&#xff0c;为学生提供个性化的学习路径和资源。 1. 环境…

在Go语言中实现HTTP请求的缓存

大家好&#xff0c;我是你们可爱的编程小助手&#xff0c;今天我们要一起探讨如何使用Go语言实现HTTP请求的缓存。听起来是不是很酷&#xff1f;让我们开始吧&#xff01; 首先&#xff0c;我们要明白什么是缓存。简单来说&#xff0c;缓存就是将数据存储在内存中&#xff0c;…

从 WasmEdge 运行环境读写 Rust Wasm 应用的时序数据

WebAssembly (Wasm) 正在成为一个广受欢迎的编译目标&#xff0c;帮助开发者构建可迁移平台的应用。最近 Greptime 和 WasmEdge 协作&#xff0c;支持了在 WasmEdge 平台上的 Wasm 应用通过 MySQL 协议读写 GreptimeDB 中的时序数据。 什么是 WebAssembly WebAssembly 是一种…

Mysql中 distinct 和 group by 哪个效率高?

结论 先说结论 有索引的情况下&#xff1a;group by和distinct都能使用索引&#xff0c;效率相同 无索引的情况下&#xff1a;distinct效率高于group by。原因是distinct 和 group by都会进行分组操作&#xff0c;但group by可能会进行排序&#xff0c;触发filesort&#xff…

DevC++ easyx 从图片放缩理解双线性插值意义

很久就想实现的一个功能&#xff0c;图片能够拖动&#xff0c;图片能够通过视口局部显示&#xff0c;但是图片放大缩小还是解决。 于是心心念念半年过去了。 恰逢校园地图大作业&#xff0c;按意思来说是可视化&#xff0c;想着能不能改改代码&#xff0c;搓一个地图&#xf…

Flutter配置Android和IOS允许http访问

默认情况下&#xff0c;Android和IOS只支持对https的访问&#xff0c;如果需要访问不安全的连接&#xff0c;也就是http&#xff0c;需要做以下配置。 Android 在res目录下的xml目录中(如果不存在&#xff0c;先创建xml目录)&#xff0c;创建一个xml文件network_security_con…

Appium+python自动化(三)- SDK Manager(超详解)

简介 本来宏哥一开始打算用真机做的&#xff0c;所以在前边搭建环境时候就没有下载SDK&#xff0c;但是由于许多小伙伴通过博客发短消息给宏哥留言说是没有真机&#xff0c;所以顺应民意整理一下模拟器&#xff0c;毕竟“得民心者&#xff0c;得天下”。SDK顾名思义&#xff0c…

【Linux学习笔记】Linux下nginx环境搭建

1、下载nginx 安装rpm命令: rpm ivh nginx-release.rpm。(直接使用linux命令下载wget http://nginx.org/packages/rhel/6/noarch/RPMS/nginx-release-rhel-6-0.el6.ngx.noarch.rpm 2、设置nginx开机启动 chkconfig nginx on 3、开启nginx服务 方法一&#xff1a;service nginx…

引力魔方的基础知识总结

1.简介&#xff1a;引力魔方是投放推荐广告的渠道&#xff0c;融合了钻展和超推&#xff1b;更新升级平台之后统一叫做人群精准推广&#xff1b; 2.展位&#xff1a;包括淘宝首页、内页频道页、门户、帮派、画报等多个淘宝站内广告位 &#xff0c;每天拥有超过8亿的展现量&…

统一身份认证,构建数字时代的安全壁垒——统一身份认证介绍、原理和实现方法

前言 随着数字化时代的来临&#xff0c;个人和机构在互联网上的活动越来越频繁&#xff0c;对于身份认证的需求也愈发迫切。为了有效应对身份欺诈、数据泄露等问题&#xff0c;统一身份认证&#xff08;Unified Identity Authentication&#xff09;应运而生。 在本文博主将介…

快速排序:高效分割与递归,排序领域的王者算法

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《数据结构&算法》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! &#x1f4cb; 前言 快速排序这个名词&#xff0c;快排之所以叫快排肯定是有点东西的。他在处理大规模数据集时表现及其…

MySQL数据库编译及安装

将安装mysql 所需软件包传到/opt目录下 cd /opt mysql-5.7.20.tar.gz boost_1_59_0.tar.gz #支持c的运行库 安装环境依赖包 yum -y install \ gcc \ gcc-c \ ncurses \ #字符终端下图形互动功能的动态库 ncurses-devel \ #ncurses开发包 bison \ #语法分析器 cmake #mysql需…