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

简介: 虚拟线程(Virtual Thread)也称协程或纤程,是一种轻量级的线程实现,与传统的线程以及操作系统级别的线程(也称为平台线程)相比,它的创建开销更小、资源利用率更高,是 Java 并发编程领域的一项重要创新。> PS:虚拟线程正式发布于 Java 长期支持版(Long Term Suort,LTS)Java 21(也就是 JDK 21)。虚拟线程是一种在 Java 虚拟机(JVM)层面实现的逻辑线程,不直接和操作系统的物理线程一一对应,因此它可以减少上下文切换所带来的性能开销。操作系统线程、普通线程(Java 线程)和虚拟线程的关系如下:![image.png](https:

虚拟线程(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、设计模式、消息队列等模块。

相关文章
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
2月前
|
算法 NoSQL Java
Springboot3新特性:GraalVM Native Image Support和虚拟线程(从入门到精通)
这篇文章介绍了Spring Boot 3中GraalVM Native Image Support的新特性,提供了将Spring Boot Web项目转换为可执行文件的步骤,并探讨了虚拟线程在Spring Boot中的使用,包括如何配置和启动虚拟线程支持。
130 9
Springboot3新特性:GraalVM Native Image Support和虚拟线程(从入门到精通)
|
2月前
|
Java 关系型数据库 MySQL
如何用java的虚拟线程连接数据库
本文介绍了如何使用Java虚拟线程连接数据库,包括设置JDK版本、创建虚拟线程的方法和使用虚拟线程连接MySQL数据库的示例代码。
65 6
如何用java的虚拟线程连接数据库
|
3月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
485 37
|
2月前
|
架构师 Java 开发者
得物面试:Springboot自动装配机制是什么?如何控制一个bean 是否加载,使用什么注解?
在40岁老架构师尼恩的读者交流群中,近期多位读者成功获得了知名互联网企业的面试机会,如得物、阿里、滴滴等。然而,面对“Spring Boot自动装配机制”等核心面试题,部分读者因准备不足而未能顺利通过。为此,尼恩团队将系统化梳理和总结这一主题,帮助大家全面提升技术水平,让面试官“爱到不能自已”。
得物面试:Springboot自动装配机制是什么?如何控制一个bean 是否加载,使用什么注解?
|
3月前
|
缓存 Java 应用服务中间件
Java虚拟线程探究与性能解析
本文主要介绍了阿里云在Java-虚拟-线程任务中的新进展和技术细节。
132 23
|
2月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
180 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
2月前
|
监控 Java API
|
2月前
|
Java 应用服务中间件 测试技术
Java21虚拟线程:我的锁去哪儿了?
【10月更文挑战第8天】
46 0
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。