首页 > 其他分享 >网易面试:SpringBoot如何开启虚拟线程?

网易面试:SpringBoot如何开启虚拟线程?

时间:2024-06-12 14:35:49浏览次数:18  
标签:SpringBoot Thread 创建 springframework 面试 虚拟 线程 import

虚拟线程(Virtual Thread)也称协程或纤程,是一种轻量级的线程实现,与传统的线程以及操作系统级别的线程(也称为平台线程)相比,它的创建开销更小、资源利用率更高,是 Java 并发编程领域的一项重要创新。

PS:虚拟线程正式发布于 Java 长期支持版(Long Term Suort,LTS)Java 21(也就是 JDK 21)。

虚拟线程是一种在 Java 虚拟机(JVM)层面实现的逻辑线程,不直接和操作系统的物理线程一一对应,因此它可以减少上下文切换所带来的性能开销。

操作系统线程、普通线程(Java 线程)和虚拟线程的关系如下:
image.png

1.虚拟线程使用

虚拟线程的创建有以下 4 种方式:

  1. Thread.startVirtualThread(Runnable task)
  2. Thread.ofVirtual().unstarted(Runnable task)
  3. Thread.ofVirtual().factory()
  4. Executors.newVirtualThreadPerTaskExecutor()

具体使用如下。

1.1 startVirtualThread

创建虚拟线程,并直接启动执行任务:

// 创建并启动虚拟线程
Thread.startVirtualThread(() -> {
    System.out.println("Do virtual thread.");
});

1.2 unstarted

只创建虚拟线程,但不直接启动(创建之后通过 start 启动):

// 创建虚拟线程
Thread vt = Thread.ofVirtual().unstarted(()->{
    System.out.println("Do virtual thread.");
});
// 运行虚拟线程
vt.start();

1.3 factory

先创建虚拟线程工厂,然后再使用工厂创建虚拟线程,之后再调用 start() 方法进行执行:

// 创建虚拟线程工厂
ThreadFactory tf = Thread.ofVirtual().factory();
// 创建虚拟线程
Thread vt = tf.newThread(()->{
    System.out.println("Do virtual thread.");
});
// 运行虚拟线程
vt.start();

1.4 newVirtualThreadPerTaskExecutor

创建虚拟线程池:

// 创建一个支持虚拟线程的线程池
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(()->{
    System.out.println("Do virtual thread.");
});

2.虚拟线程 VS 普通线程

虚拟线程和普通线程的区别主要体现在以下几点:

  1. 普通线程是和操作系统的物理线程是一一对应的,而虚拟线程是 JVM 层面的逻辑线程,并不和操作系统的物理线程一一对应,它可以看作是轻量级的线程。
  2. 普通线程默认创建的是用户线程(而守护线程),而虚拟线程是守护线程,并且其守护线程的属性不能被修改,如果修改就会报错,如下图所示:

  1. 虚拟线程由 JVM 调度和使用,避免了普通线程频繁切换的性能开销,所以相比于普通的线程来说,运行效率更高。

3.SpringBoot开启虚拟线程

以最新版的 Spring Boot 3.x 为例,我们开启虚拟线程很简单,只需要在 Spring Boot 配置文件中设置“spring.threads.virtual.enabled”为“true”即可开启,以 application.yml 为例,启用虚拟线程配置如下:

spring:
  threads:
    virtual:
      enabled: true # 启用虚拟线程

这样 Spinrg Boot 在启动 Tomcat 容器时,会使用一个虚拟线程执行器来代表原有的平台线程池。

PS:这里是虚拟线程执行器,不是虚拟线程池。

如果以上配置未生效的话,还可以通过修改 Tomcat 配置类,让其使用虚拟线程来处理每一个请求,配置代码如下:

import java.util.concurrent.Executors;

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

@Configuration
public class TomcatConfiguration {
    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> {
            // 使用虚拟线程来处理每一个请求
            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
        };
    }
}

4.异步任务开启虚拟线程

如果你想为 Spring Boot 中的异步任务 @Async 也配置虚拟线程的话,可以在 AsyncConfigurer 配置类中设置,配置代码如下:

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.support.TaskExecutorAdapter;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;

@Configuration
@EnableAsync  // 开启异步任务
public class AsyncTaskConfiguration implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        return new TaskExecutorAdapter(Executors.newThreadPerTaskExecutor(Thread.ofVirtual().name("virtual-async#", 1).factory()));
    }
}

课后思考

说说虚拟线程的底层实现?有了虚拟线程后还需要虚拟线程池吗?为什么?

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

标签:SpringBoot,Thread,创建,springframework,面试,虚拟,线程,import
From: https://www.cnblogs.com/vipstone/p/18243885

相关文章

  • SpringBoot面试准备 第一天
    什么是SpringBoot?简化Spring 应用程序开发的框架,通过自动配置、起步依赖和简化的配置方式,使开发人员能够更快速、方便地创建和配置Spring应用程序,提高开发效率和开发体验目标是使开发人员能够更加快速、方便地创建和配置Spring应用程序,同时尽可能地减少样板代码和繁琐......
  • 【接口自动化测试框架练习】springboot+react+mysql~极简版postman
    可以说是一个toyprogram,chatgpt完成了一部分工作,我也完成了一部分工作,我俩合作的,我占百分之80%,他百分之20%,哈哈没他不行,源码奉上。https://github.com/Jinwenxin/test-api-frontend1.功能简介:分成三部分,如左侧导航栏所示:测试用例管理:测试用例的增删改查以及运行测试套件管理......
  • 【S087】Springboot+Thymleaf在线答疑系统项目源码 java源代码
    运行截图:登录学生注册教师注册学生发起问题联系我们后台首页常见问题管理添加常见问题人工答疑学生管理个人信息修改密码项目组成:项目源码:源码获取⬇⬇⬇......
  • 【S086】基于Springboot图书馆管理系统项目源码 java图书借阅管理 含文档
    运行截图:登录后台主页图书列表图书上架借阅图书归还图书用户列表添加用户公告列表发布公告个人信息详情个人信息编辑项目组成:项目源码:项目文档:源码获取⬇⬇⬇......
  • Springboot自动配置的原理剖析
    @SpringBootApplication注解分析1、我们都知道Springboot的启动入口来自这个注解@SpringBootApplication,里面详细如下图2、再进一步细化如下图,那么应该是使用哪种方式来加载Springboot的自动配置类呢直接上结论,Springboot的自动配置实现方式是通过@Import注解实现的,首先......
  • Interlocked 为多个线程共享的变量提供原子操作 多线程重入
    Interlocked可以为多个线程共享的变量提供原子操作主要使用的读写方法varrunningState=Interlocked.Read(refisRunning);Interlocked.Exchange(refisRunning,0);可以配合lock实现业务常用方法Add(Int32,Int32) 对两个32位整数进行求和并用和替换第一个整数,上述操......
  • springboot异常解决
    问题解决问题解释Resolved[org.springframework.http.converter.HttpMessageNotWritableException:Noconverterfor[classcom.test.entity.User]withpresetContent-Type'null']”出现这个问题表明spring在尝试将user对象序列化为http响应时,找不到适当的消息转化器。......
  • 【mysql】PROCESSLIST 查看运行中的线程
    发现mysql语句查询响应特别慢,想看一下mysql现时正在做什么事情?通过以下语句,可以看mysql有哪些线程正在运行,也可以帮助定位问题。比如有一些运行特别久的语句。用这个语句看一下:showprocesslistshowfullprocesslist或者用这个语句:select*frominformation_schema.`......
  • 一文带你搞清楚Python的多线程和多进程
    本文分享自华为云社区《Python中的多线程与多进程编程大全【python指南】》,作者:柠檬味拥抱。Python作为一种高级编程语言,提供了多种并发编程的方式,其中多线程与多进程是最常见的两种方式之一。在本文中,我们将探讨Python中多线程与多进程的概念、区别以及如何使用线程池与进程池来......
  • springboot打包将配置文件和jar分开
    <?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="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......