网站首页 > java教程 正文
虚拟线程(Virtual Thread)也称协程或纤程,是一种轻量级的线程实现,与传统的线程以及操作系统级别的线程(也称为平台线程)相比,它的创建开销更小、资源利用率更高,是 Java 并发编程领域的一项重要创新。
PS:虚拟线程正式发布于 Java 长期支持版(Long Term Suort,LTS)Java 21(也就是 JDK 21)。
虚拟线程是一种在 Java 虚拟机(JVM)层面实现的逻辑线程,不直接和操作系统的物理线程一一对应,因此它可以减少上下文切换所带来的性能开销。
操作系统线程、普通线程(Java 线程)和虚拟线程的关系如下:
1.虚拟线程使用
虚拟线程的创建有以下 4 种方式:
- Thread.startVirtualThread(Runnable task)
- Thread.ofVirtual().unstarted(Runnable task)
- Thread.ofVirtual().factory()
- 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 普通线程
虚拟线程和普通线程的区别主要体现在以下几点:
- 普通线程是和操作系统的物理线程是一一对应的,而虚拟线程是 JVM 层面的逻辑线程,并不和操作系统的物理线程一一对应,它可以看作是轻量级的线程。
- 普通线程默认创建的是用户线程(而守护线程),而虚拟线程是守护线程,并且其守护线程的属性不能被修改,如果修改就会报错,如下图所示:
- 虚拟线程由 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](https://www.javacn.site),其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。
猜你喜欢
- 2025-05-30 线程池的使用及ThreadPoolExecutor源码分析
- 2025-05-30 面试官:什么是虚拟线程?为什么要有虚拟线程?
- 2025-05-30 「超级详细」Java线程实现原理
- 2025-05-30 并发编程之ThreadPoolExecutor线程池原理解析
- 2025-05-30 阿里资深架构推荐学习四本实战书籍:MySQL+Redis+Kfaka+多线程
- 2025-05-30 杰哥教你面试之一百问系列:java多线程
- 2025-05-30 面试突击29:说一下线程池7个参数的含义?
- 2025-05-30 一个 tomcat 项目使用多个线程池还是一个线程池 ?
- 2025-05-30 一个注解 —— 完美实现分布式锁
- 2025-05-30 Java 线程的生命周期及各阶段状态
你 发表评论:
欢迎- 06-04C++优先级调度队列(Priority Queue)
- 06-04数据结构与算法-优先队列(优先队列 数组实现)
- 06-04什么是优先队列?(优先队列原理)
- 06-04终于有架构大牛把分布式系统概念讲明白了,竟然用了足足800页
- 06-04分布式事物如何保证接口请求顺序性?
- 06-04微服务下分布式事务模式的详细对比
- 06-04彻底掌握分布式事务2PC、3PC模型(分布式事务 三阶段)
- 06-04分布式事务最全详解(看这篇就够了)
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)