Java21在spring boot中使用虚拟线程的方法

 更新时间:2025年08月23日 14:51:16   作者:不死的精灵  
本文给大家介绍Java21在spring boot中使用虚拟线程的方法,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

前置知识

虚拟线程VT(Virtual Thread)

0.环境说明

用于验证的版本:

spring boot 3.1中就支持使用jdk21的虚拟线程了,但是在spring boot 3.2中可以直接通过配置的方式开启虚拟线程。不过本文编写的时候spring boot 3.3.3已经GA了,他在3.2的基础上又对虚拟线程进行了进一步地适配,所以本文章中的版本为3.3

在spring boot 3.2.9中配置spring.threads.virtual.enabled=true即可启用虚拟线程

1.原理解析

开启了这个配置后,对我们的spring boot服务有什么影响呢?

我们在spring boot的源码中搜索spring.threads.virtual.enabled即可看到这个配置在spring boot中生效在了什么地方。
首先我们可以看到如下的代码(通过代码注释也能看出,这个配置就是在3.2.0引入的)

/**
 * Threading of the application.
 *
 * @author Moritz Halbritter
 * @since 3.2.0
 */
public enum Threading {
	/**
	 * Platform threads. Active if virtual threads are not active.
	 */
	PLATFORM {
		@Override
		public boolean isActive(Environment environment) {
			return !VIRTUAL.isActive(environment);
		}
	},
	/**
	 * Virtual threads. Active if {@code spring.threads.virtual.enabled} is {@code true}
	 * and running on Java 21 or later.
	 */
	VIRTUAL {
		@Override
		public boolean isActive(Environment environment) {
			return environment.getProperty("spring.threads.virtual.enabled", boolean.class, false)
					&& JavaVersion.getJavaVersion().isEqualOrNewerThan(JavaVersion.TWENTY_ONE);
		}
	};
	/**
	 * Determines whether the threading is active.
	 * @param environment the environment
	 * @return whether the threading is active
	 */
	public abstract boolean isActive(Environment environment);
}

接下来我们看一下VIRTUAL.isActive(environment)这个方法都用在了哪里(哪里用到了,就说明哪里的虚拟线程是通过这个配置生效的)

可以看到他被用在如下的地方:

  • spring-webflux(区别于spring web的一个响应式web开发框架)的阻塞配置中(如果阻塞了使用什么类型的线程去进行阻塞)
  • 注解ConditionalOnThreading的判断条件OnThreadingCondition
    • Rabbit MQ——一个消息队列,启用虚拟线程则执行configurer.setTaskExecutor(new VirtualThreadTaskExecutor("rabbit-direct-"));configurer.setTaskExecutor(new VirtualThreadTaskExecutor("rabbit-simple-"));
    • JedisConnection——一个redis客户端,启用虚拟线程则执行
      SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("redis-");
          executor.setVirtualThreads(true);
          factory.setExecutor(executor);
    • LettuceConnection——一个redis客户端,启用虚拟线程则执行和Jedis类似的代码,都是把Executor设置为一个启用了虚拟线程的new SimpleAsyncTaskExecutor("redis-");
    • Kafka——一个消息队列,启用虚拟线程则执行和Jedis类似的两码,把Executor设置为一个启用了虚拟线程的new SimpleAsyncTaskExecutor("kafka-");
    • TaskExecutorConfigurations——spring boot中的任务调度器配置类,@Async(异步任务注解)所注解的方法会根据配置决定是用平台线程执行还是虚拟线程执行
    • TaskSchedulingConfigurations——spring boot中定时任务配置类,@Scheduled(定时任务注解)所注解的方法会根据配置决定是用平台线程执行还是虚拟线程执行
    • EmbeddedWebServerFactoryCustomizerAutoConfiguration——通常我们最关心的地方,这里定义了spring web的默认容器tomcat的线程配置(Jetty的工作线程配置也在一起),如果开启了虚拟线程,则tomcat会使用虚拟线程作为执行器(再也不用考虑tomcat默认200线程的问题了!!!)
  • Pulsar:一个分布式消息流平台,启用虚拟线程则执行containerProperties.setConsumerTaskExecutor(new VirtualThreadTaskExecutor("pulsar-consumer-"));readerContainerProperties.setReaderTaskExecutor(new VirtualThreadTaskExecutor("pulsar-reader-"));

2.spring boot的方案

通过在spring boot的源码搜索@ConditionalOnThreading(Threading.VIRTUAL),可以看到spring boot会根据虚拟线程的开启与否来选择注入不同的bean,我们以spring-data-redis为例,其具体代码如下:

    @Bean
	@ConditionalOnMissingBean(RedisConnectionFactory.class)
	@ConditionalOnThreading(Threading.PLATFORM)
	LettuceConnectionFactory redisConnectionFactory(
			ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
			ClientResources clientResources) {
		return createConnectionFactory(builderCustomizers, clientResources);
	}
	@Bean
	@ConditionalOnMissingBean(RedisConnectionFactory.class)
	@ConditionalOnThreading(Threading.VIRTUAL)
	LettuceConnectionFactory redisConnectionFactoryVirtualThreads(
			ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
			ClientResources clientResources) {
		LettuceConnectionFactory factory = createConnectionFactory(builderCustomizers, clientResources);
		SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("redis-");
		executor.setVirtualThreads(true);
		factory.setExecutor(executor);
		return factory;
	}

通过代码不难看出,spring boot 3.2通过@ConditionalOnThreading注解的方式,实现了虚拟线程和平台线程的动态配置。

如果我们自己需要开发一个能够同时支持平台线程和虚拟线程的sdk,可以复用这个注解。

3.注意事项(施工中,欢迎补充)

  • 使用虚拟线程本身要注意的5个点:
    1. 大方使用“一个请求一个线程”的开发方式
    2. 不需要对虚拟线程进行池化
    3. 使用信号量控制并发
    4. 慎用ThreadLocal,使用ScopeValue(java21中还是预览状态)代替
    5. 使用ReturnLock替代synchronized(这个问题似乎在jdk23中会永久解决)
  • java21默认的垃圾回收器G1和其自身的JIT编译器C2似乎有冲突,会导致jvm crash?(这里不能确定,似乎在高版本jdk 21.0.7中进行了修复,但是我比较了openjdk的源码,并没能找到具体的改动指向这个问题)

到此这篇关于Java21在spring boot中使用虚拟线程的方法的文章就介绍到这了,更多相关springboot使用虚拟线程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java基础之教你怎么用代码一键生成POJO

    Java基础之教你怎么用代码一键生成POJO

    这篇文章主要介绍了Java基础之教你怎么用代码一键生成POJO,文中有非常详细的代码示例,对正在学习Java的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • java读取证书公钥的实现

    java读取证书公钥的实现

    这篇文章主要介绍了java读取证书公钥的实现,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • Java实现优雅日期处理的方案详解

    Java实现优雅日期处理的方案详解

    在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-04-04
  • Java中使用ConcurrentHashMap实现线程安全的Map

    Java中使用ConcurrentHashMap实现线程安全的Map

    在Java中,ConcurrentHashMap是一种线程安全的哈希表,可用于实现多线程环境下的Map操作。它支持高并发的读写操作,通过分段锁的方式实现线程安全,同时提供了一些高级功能,比如迭代器弱一致性和批量操作等。ConcurrentHashMap在高并发场景中具有重要的应用价值
    2023-04-04
  • Mybatis结果集映射与生命周期详细介绍

    Mybatis结果集映射与生命周期详细介绍

    结果集映射指的是将数据表中的字段与实体类中的属性关联起来,这样 MyBatis 就可以根据查询到的数据来填充实体对象的属性,帮助我们完成赋值操作
    2022-10-10
  • 详解SpringBoot 快速整合MyBatis(去XML化)

    详解SpringBoot 快速整合MyBatis(去XML化)

    本篇文章主要介绍了详解SpringBoot 快速整合MyBatis(去XML化),非常具有实用价值,需要的朋友可以参考下
    2017-10-10
  • SpringCloud客户端的负载均衡Ribbon的实现

    SpringCloud客户端的负载均衡Ribbon的实现

    微服务架构,不可避免的存在单个微服务有多个实例,这篇文章主要介绍了SpringCloud客户端的负载均衡Ribbon的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • 关于@CacheEvict无法解决分页缓存清除的解决思路

    关于@CacheEvict无法解决分页缓存清除的解决思路

    这篇文章主要介绍了关于@CacheEvict无法解决分页缓存清除的解决思路,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • SpringBoot整合Guava Cache实现全局缓存的示例代码

    SpringBoot整合Guava Cache实现全局缓存的示例代码

    这篇文章主要介绍了SpringBoot整合Guava Cache实现全局缓存,Guava Cache是Google Guava库中的一个模块,提供了基于内存的本地缓存实现,文中介绍了SpringBoot整合使用Guava Cache的具体步骤,需要的朋友可以参考下
    2024-03-03
  • Mybatis-plus 双主键的实现示例

    Mybatis-plus 双主键的实现示例

    本文主要介绍了Mybatis-plus 双主键的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05

最新评论