我们有一个GetMapping返回所有结果 , 我们的数据库中有 1000 条数据 。我们已经让线程休眠 1 秒 。让我们看看我们的Product实体和ProductRepository 。
package org.anil.virtualthread;import jakarta.persistence.Entity;import jakarta.persistence.GeneratedValue;import jakarta.persistence.GenerationType;import jakarta.persistence.Id;import lombok.Getter;import lombok.Setter;@Entity@Getter@Setterpublic class Product {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String productName;private Long price;}package org.anil.virtualthread;import org.springframework.data.jpa.repository.JpaRepository;public interface ProductRepository extends JpaRepository<Product,Long> {}
【SpringBoot+虚拟线程,接口吞吐量成倍增加,太爽了!】让我们看看我们的 application.yaml
spring:datasource:driver-class-name: com.mysql.cj.jdbc.DrivermaxIdle: 1timeBetweenEvictionRunsMillis: 60000hikari:connection-timeout: 60000maximum-pool-size: 10minimum-idle: 5url: jdbc:mysql://localhost:3306/todostestWhileIdle: trueusername: rootpassword: root1234validationQuery: SELECT 1flyway:baseline-version: 0enabled: truevalidate-on-migrate: falsejpa:database: mysqlgenerate-ddl: truehibernate:ddl-auto: noneformat_sql: trueshow-sql: true
现在,我们首先通过注释以下行来运行应用程序,这将在普通线程上运行我们的应用程序 。
package org.anil.virtualthread;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;import org.springframework.context.annotation.Bean;import java.util.concurrent.Executors;@SpringBootApplication@Slf4jpublic class VirtualthreadApplication {public static void main(String[] args) {SpringApplication.run(VirtualthreadApplication.class, args);}//@Bean//public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {//return protocolHandler -> {//log.info("Configuring " + protocolHandler + " to use VirtualThreadPerTaskExecutor");//protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());//};//}}
现在让我们设置JMeter 。我们将有 1000 个请求,该请求将在 3 秒内增加 。并且这样的状态会持续200秒 。每 3 秒,将触发 1000 个 GET (“/thread”) 请求 。我们还添加了响应时间图侦听器 。
文章插图
现在让我们运行测试并等待 200 秒 。
文章插图
从图中我们可以看到,一旦Tomcat的整个线程池被利用,响应时间从3600毫秒猛增到5200毫秒 。从那时起,只有当以前的线程被释放时,它才保持这种状态 。
现在让我们在启用虚拟线程功能的情况下运行负载测试 。
package org.anil.virtualthread;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;import org.springframework.context.annotation.Bean;import java.util.concurrent.Executors;@SpringBootApplication@Slf4jpublic class VirtualthreadApplication {public static void main(String[] args) {SpringApplication.run(VirtualthreadApplication.class, args);}@Beanpublic TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {return protocolHandler -> {log.info("Configuring " + protocolHandler + " to use VirtualThreadPerTaskExecutor");protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());};}}
现在让我们运行测试并等待 200 秒 。文章插图
显然,现在并发 1000 个请求的响应时间几乎略高于 1000 毫秒 , 有时甚至会达到 1400 毫秒,这比我们使用普通线程时要好得多 。
显然,当我们需要充分利用底层 CPU 时 , 我们应该开始在应用程序中采用虚拟线程,突然间我们可以看到,对于相同的硬件,应用程序的吞吐量增加了很多倍 。
这比切换到反应式编程要好得多,反应式编程意味着重写所有代码,这很难先学习,然后编写,甚至更难调试和分析 。
简而言之,更多用户可以使用该应用程序并与第一个用户同时获得响应 。
推荐阅读
- JVM 理解Java虚拟机:优化代码执行效率的内部机制
- 直播行业生态格局不断演变,数字人虚拟主播成新兴力量
- 什么是线程组?你学会了吗?
- 特殊线程池ForkJoinPool 要合理运用,不是什么样的任务都拿来用
- Java网络代理:探索代理服务器与虚拟网络技术
- 十分钟搞定前端虚拟列表
- 在Python中什么场景下应该使用多进程和多线程?
- Kubernetes:裸机vs虚拟机性能对比
- 换手机了,老手机里的虚拟交通卡能继续使用吗?来看权威解答
- 手机的虚拟网络是什么意思啊怎么设置 手机的虚拟网络是什么意思啊