6人参与 • 2026-03-18 • Java
java 21引入了虚拟线程(virtual threads),这是project loom的核心特性。虚拟线程是轻量级线程,可以显著提高应用程序的并发处理能力,特别适合i/o密集型任务。
在spring boot 3.2+中,已经内置了对虚拟线程的支持,可以通过简单的配置启用。
在 application.yml 中已经配置:
spring:
threads:
virtual:
enabled: true
这个配置会自动:
@async 方法启用虚拟线程执行器可以通过以下方式验证:
@springboottest
public class virtualthreadtest {
@test
public void testvirtualthread() {
thread thread = thread.ofvirtual().start(() -> {
system.out.println("虚拟线程名称: " + thread.currentthread().getname());
system.out.println("是否为虚拟线程: " + thread.currentthread().isvirtual());
});
try {
thread.join();
} catch (interruptedexception e) {
thread.currentthread().interrupt();
}
}
}
配置类改造(推荐):
/**
* 异步线程池配置(虚拟线程版本)
* 当 spring.threads.virtual.enabled=true 时使用虚拟线程
*
* @author
* @date 2024-10-31
*/
@slf4j
@configuration
@enableasync
public class virtualthreadasyncconfig implements asyncconfigurer {
/**
* 虚拟线程异步执行器
* spring boot 3.2+ 会自动创建虚拟线程执行器,这里提供手动配置示例
*/
@bean(name = "virtualthreadexecutor")
@conditionalonproperty(name = "spring.threads.virtual.enabled", havingvalue = "true", matchifmissing = false)
public executor virtualthreadexecutor() {
return new taskexecutoradapter(executors.newvirtualthreadpertaskexecutor());
}
/**
* 默认异步执行器
* 如果启用虚拟线程,spring boot会自动使用虚拟线程执行器
*/
@override
public executor getasyncexecutor() {
// spring boot 3.2+ 会自动使用虚拟线程执行器(如果启用)
// 如果需要手动指定,可以返回 virtualthreadexecutor()
return executors.newvirtualthreadpertaskexecutor();
}
@override
public asyncuncaughtexceptionhandler getasyncuncaughtexceptionhandler() {
return new simpleasyncuncaughtexceptionhandler();
}
}
使用示例:
@service
@slf4j
public class exampleservice {
/**
* 使用默认虚拟线程执行器
*/
@async
public completablefuture<string> asyncmethod1() {
log.info("当前线程: {}, 是否为虚拟线程: {}",
thread.currentthread().getname(),
thread.currentthread().isvirtual());
// 执行异步任务
return completablefuture.completedfuture("完成");
}
/**
* 指定使用虚拟线程执行器
*/
@async("virtualthreadexecutor")
public completablefuture<string> asyncmethod2() {
log.info("当前线程: {}, 是否为虚拟线程: {}",
thread.currentthread().getname(),
thread.currentthread().isvirtual());
return completablefuture.completedfuture("完成");
}
}
spring boot 3.2+ 启用虚拟线程后,所有web请求会自动使用虚拟线程处理,无需额外配置。
验证方式:
@restcontroller
@requestmapping("/api/test")
@slf4j
public class virtualthreadtestcontroller {
@getmapping("/virtual-thread")
public map<string, object> testvirtualthread() {
thread currentthread = thread.currentthread();
map<string, object> result = new hashmap<>();
result.put("threadname", currentthread.getname());
result.put("isvirtual", currentthread.isvirtual());
result.put("threadid", currentthread.threadid());
log.info("请求处理线程: {}, 是否为虚拟线程: {}",
currentthread.getname(), currentthread.isvirtual());
return result;
}
}
配置类改造:
/**
* 定时任务配置(虚拟线程版本)
*
* @author
* @date 2024-10-31
*/
@slf4j
@configuration
@enablescheduling
@conditionalonproperty(name = "spring.threads.virtual.enabled", havingvalue = "true")
public class virtualthreadschedulingconfig implements schedulingconfigurer {
@override
public void configuretasks(scheduledtaskregistrar taskregistrar) {
taskregistrar.setscheduler(taskscheduler());
}
@bean
public executor taskscheduler() {
return executors.newvirtualthreadpertaskexecutor();
}
}
使用示例:
@component
@slf4j
public class scheduledtaskexample {
/**
* 定时任务会自动使用虚拟线程执行器
*/
@scheduled(fixedrate = 5000)
public void scheduledtask() {
log.info("定时任务执行 - 线程: {}, 是否为虚拟线程: {}",
thread.currentthread().getname(),
thread.currentthread().isvirtual());
}
}
/**
* 虚拟线程工具类(改进版)
*
* @author
* @date 2024-10-31
*/
@slf4j
@component
public class virtualthreadutils {
private static final executorservice executor = executors.newvirtualthreadpertaskexecutor();
/**
* 执行虚拟线程任务
*
* @param task 任务
* @return future
*/
public static future<?> exevirtualthread(runnable task) {
return executor.submit(() -> {
try {
log.debug("虚拟线程执行任务 - 线程: {}, 是否为虚拟线程: {}",
thread.currentthread().getname(),
thread.currentthread().isvirtual());
task.run();
} catch (exception e) {
log.error("虚拟线程执行任务异常", e);
throw e;
}
});
}
/**
* 执行虚拟线程任务(带返回值)
*
* @param task 任务
* @param <t> 返回值类型
* @return future
*/
public static <t> future<t> exevirtualthread(java.util.concurrent.callable<t> task) {
return executor.submit(() -> {
try {
log.debug("虚拟线程执行任务 - 线程: {}, 是否为虚拟线程: {}",
thread.currentthread().getname(),
thread.currentthread().isvirtual());
return task.call();
} catch (exception e) {
log.error("虚拟线程执行任务异常", e);
throw e;
}
});
}
@predestroy
public void destroy() {
log.info("关闭虚拟线程执行器");
executor.shutdown();
try {
if (!executor.awaittermination(60, timeunit.seconds)) {
executor.shutdownnow();
if (!executor.awaittermination(60, timeunit.seconds)) {
log.error("虚拟线程执行器未能正常关闭");
}
}
} catch (interruptedexception e) {
executor.shutdownnow();
thread.currentthread().interrupt();
}
}
}
@service
@slf4j
public class completablefutureexample {
/**
* 使用虚拟线程执行器执行completablefuture
*/
public completablefuture<list<string>> processdataasync() {
executor virtualexecutor = executors.newvirtualthreadpertaskexecutor();
completablefuture<list<string>> future = completablefuture
.supplyasync(() -> {
log.info("异步任务执行 - 线程: {}, 是否为虚拟线程: {}",
thread.currentthread().getname(),
thread.currentthread().isvirtual());
return fetchdata();
}, virtualexecutor)
.thenapplyasync(data -> {
log.info("处理数据 - 线程: {}, 是否为虚拟线程: {}",
thread.currentthread().getname(),
thread.currentthread().isvirtual());
return processdata(data);
}, virtualexecutor);
return future;
}
private list<string> fetchdata() {
// 模拟i/o操作
try {
thread.sleep(100);
} catch (interruptedexception e) {
thread.currentthread().interrupt();
}
return arrays.aslist("data1", "data2", "data3");
}
private list<string> processdata(list<string> data) {
return data.stream()
.map(string::touppercase)
.collect(collectors.tolist());
}
}
/**
* rabbitmq虚拟线程配置
*
* @author 往事随风去
* @date 2024-10-31
*/
@slf4j
@configuration
@conditionalonproperty(name = "spring.threads.virtual.enabled", havingvalue = "true")
public class rabbitmqvirtualthreadconfig {
@bean
public simplerabbitlistenercontainerfactory rabbitlistenercontainerfactory(
connectionfactory connectionfactory) {
simplerabbitlistenercontainerfactory factory = new simplerabbitlistenercontainerfactory();
factory.setconnectionfactory(connectionfactory);
// 使用虚拟线程执行器处理消息
factory.settaskexecutor(new taskexecutoradapter(executors.newvirtualthreadpertaskexecutor()));
return factory;
}
}
对于mybatis等数据库操作,通常不需要特别配置,因为:
虚拟线程适合:
虚拟线程不适合:
虚拟线程会频繁切换,threadlocal的使用需要注意:
// ❌ 不推荐:在虚拟线程中使用threadlocal存储大量数据 threadlocal<list<string>> threadlocal = new threadlocal<>(); // ✅ 推荐:使用scopedvalue(java 21+)或谨慎使用threadlocal scopedvalue<string> scopedvalue = scopedvalue.newinstance();
启用虚拟线程后,不需要配置线程池大小,虚拟线程会自动管理:
# ❌ 不需要配置这些(虚拟线程会自动管理)
server:
tomcat:
threads:
max: 400 # 虚拟线程模式下无效
min-spare: 100 # 虚拟线程模式下无效
虚拟线程的监控需要使用新的api:
@service
@slf4j
public class virtualthreadmonitor {
@scheduled(fixedrate = 60000)
public void monitorvirtualthreads() {
threadmxbean threadbean = managementfactory.getthreadmxbean();
long[] threadids = threadbean.getallthreadids();
long virtualthreadcount = arrays.stream(threadids)
.maptoobj(id -> {
threadinfo info = threadbean.getthreadinfo(id);
return info != null ? thread.ofplatform().getthreadgroup()
.findthread(id) : null;
})
.filter(objects::nonnull)
.filter(thread::isvirtual)
.count();
log.info("虚拟线程数量: {}", virtualthreadcount);
}
}
@configuration
public class hybridthreadconfig {
/**
* cpu密集型任务使用平台线程池
*/
@bean("cpuintensiveexecutor")
public executor cpuintensiveexecutor() {
int processors = runtime.getruntime().availableprocessors();
return executors.newfixedthreadpool(processors);
}
/**
* i/o密集型任务使用虚拟线程
*/
@bean("iointensiveexecutor")
public executor iointensiveexecutor() {
return executors.newvirtualthreadpertaskexecutor();
}
}
@service
public class taskservice {
@autowired
@qualifier("cpuintensiveexecutor")
private executor cpuexecutor;
@autowired
@qualifier("iointensiveexecutor")
private executor ioexecutor;
public void processtask() {
// i/o操作使用虚拟线程
completablefuture<string> data = completablefuture
.supplyasync(this::fetchdata, ioexecutor);
// cpu计算使用平台线程
completablefuture<string> result = data
.thenapplyasync(this::heavycomputation, cpuexecutor);
}
}
第一步:启用虚拟线程
spring:
threads:
virtual:
enabled: true
第二步:改造异步配置
scheduledtaskcofiguration 改造为使用虚拟线程第三步:测试和验证
第四步:性能测试
如果出现问题,可以快速回滚:
spring:
threads:
virtual:
enabled: false # 禁用虚拟线程,恢复传统线程池
虚拟线程在spring boot中的正确使用方式:
spring.threads.virtual.enabled=true@async 自动使用虚拟线程schedulingconfigurerexecutors.newvirtualthreadpertaskexecutor()通过合理使用虚拟线程,可以显著提高i/o密集型应用的并发处理能力,减少线程资源消耗。
到此这篇关于虚拟线程在spring boot中的正确使用方式及最佳实践的文章就介绍到这了,更多相关springboot中虚拟线程使用方式内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论