spring boot 3 已经提供了对虚拟线程的支持。
虚拟线程和平台线程主要区别在于,虚拟线程在运行周期内不依赖操作系统线程:它们与硬件脱钩,因此被称为 “虚拟”。这种解耦是由 JVM 提供的抽象层赋予的。
虚拟线程的运行成本远低于平台线程。消耗的内存要少得多。这就是为什么可以创建数百万个虚拟线程而不会出现内存不足的问题,而标准平台(或内核)线程只能创建数百个。
虚拟线程会优先使用JVM提供,如果不能使用JVM提供,则考虑使用由平台线程支持的“虚拟线程” ,相关源代码参考java.lang.ThreadBuilders#newVirtualThread
4.0.0 org.springframework.boot spring-boot-starter-parent 3.2.0 net.jlxxw boot3-demo 1.0.0.20231128 boot3-demo boot3-demo 21 UTF-8 UTF-8 3.2.0 org.apache.httpcomponents.client5 httpclient5-fluent org.springframework.boot spring-boot-starter-aop org.springframework.boot spring-boot-configuration-processor org.springframework.boot spring-boot-starter-logging org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.graalvm.buildtools native-maven-plugin ${project.artifactId} org.springframework.boot spring-boot-maven-plugin
spring: #启动虚拟线程的必须配置 threads: virtual: # 启用虚拟线程技术,增加系统并发能力 enabled: true
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration.TomcatWebServerFactoryCustomizerConfiguration#tomcatVirtualThreadsProtocolHandlerCustomizer
/* * Copyright 2012-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot.autoconfigure.web.embedded; import io.undertow.Undertow; import org.apache.catalina.startup.Tomcat; import org.apache.coyote.UpgradeProtocol; import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.Loader; import org.xnio.SslClientAuthMode; import reactor.netty.http.server.HttpServer; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment; import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.thread.Threading; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; /** * {@link EnableAutoConfiguration Auto-configuration} for embedded servlet and reactive * web servers customizations. * * @author Phillip Webb * @since 2.0.0 */ @AutoConfiguration @ConditionalOnNotWarDeployment @ConditionalOnWebApplication @EnableConfigurationProperties(ServerProperties.class) public class EmbeddedWebServerFactoryCustomizerAutoConfiguration { /** * Nested configuration if Tomcat is being used. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class }) public static class TomcatWebServerFactoryCustomizerConfiguration { @Bean public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) { return new TomcatWebServerFactoryCustomizer(environment, serverProperties); } @Bean @ConditionalOnThreading(Threading.VIRTUAL) TomcatVirtualThreadsWebServerFactoryCustomizer tomcatVirtualThreadsProtocolHandlerCustomizer() { return new TomcatVirtualThreadsWebServerFactoryCustomizer(); } } /** * Nested configuration if Jetty is being used. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class }) public static class JettyWebServerFactoryCustomizerConfiguration { @Bean public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) { return new JettyWebServerFactoryCustomizer(environment, serverProperties); } @Bean @ConditionalOnThreading(Threading.VIRTUAL) JettyVirtualThreadsWebServerFactoryCustomizer jettyVirtualThreadsWebServerFactoryCustomizer( ServerProperties serverProperties) { return new JettyVirtualThreadsWebServerFactoryCustomizer(serverProperties); } } /** * Nested configuration if Undertow is being used. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ Undertow.class, SslClientAuthMode.class }) public static class UndertowWebServerFactoryCustomizerConfiguration { @Bean public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) { return new UndertowWebServerFactoryCustomizer(environment, serverProperties); } } /** * Nested configuration if Netty is being used. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(HttpServer.class) public static class NettyWebServerFactoryCustomizerConfiguration { @Bean public NettyWebServerFactoryCustomizer nettyWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties) { return new NettyWebServerFactoryCustomizer(environment, serverProperties); } } }
org.springframework.boot.autoconfigure.web.embedded.TomcatVirtualThreadsWebServerFactoryCustomizer
/* * Copyright 2012-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot.autoconfigure.web.embedded; import org.apache.coyote.ProtocolHandler; import org.apache.tomcat.util.threads.VirtualThreadExecutor; import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.core.Ordered; /** * Activates {@link VirtualThreadExecutor} on {@link ProtocolHandler Tomcat's protocol * handler}. * * @author Moritz Halbritter * @since 3.2.0 */ public class TomcatVirtualThreadsWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { @Override public void customize(ConfigurableTomcatWebServerFactory factory) { factory.addProtocolHandlerCustomizers( (protocolHandler) -> protocolHandler.setExecutor(new VirtualThreadExecutor("tomcat-handler-"))); } @Override public int getOrder() { return TomcatWebServerFactoryCustomizer.ORDER + 1; } }
org.apache.tomcat.util.threads.VirtualThreadExecutor
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.tomcat.util.threads; import java.util.concurrent.Executor; import org.apache.tomcat.util.compat.JreCompat; /** * An executor that uses a new virtual thread for each task. */ public class VirtualThreadExecutor implements Executor { private final JreCompat jreCompat = JreCompat.getInstance(); private Object threadBuilder; public VirtualThreadExecutor(String namePrefix) { threadBuilder = jreCompat.createVirtualThreadBuilder(namePrefix); } @Override public void execute(Runnable command) { jreCompat.threadBuilderStart(threadBuilder, command); } }