此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.5! |
任务执行和调度
在没有Executor
bean 中,Spring Boot 会自动配置一个AsyncTaskExecutor
.
启用虚拟线程后(使用 Java 21+ 和spring.threads.virtual.enabled
设置为true
),这将是一个SimpleAsyncTaskExecutor
使用虚拟线程。
否则,它将是一个ThreadPoolTaskExecutor
具有合理的默认值。
自动配置的AsyncTaskExecutor
用于以下集成,除非自定义Executor
bean 定义如下:
-
使用 执行异步任务
@EnableAsync
,除非AsyncConfigurer
已定义。 -
异步处理
Callable
从 Spring for GraphQL 中的控制器方法返回值。 -
Spring MVC 中的异步请求处理。
-
支持 Spring WebFlux 中的阻塞执行。
-
用于 Spring WebSocket 中的入站和出站消息通道。
-
JPA 的引导执行程序,基于 JPA 存储库的引导模式。
-
Bootstrap Executor 用于
ApplicationContext
.
虽然这种方法在大多数情况下都有效,但 Spring Boot 允许您覆盖自动配置的AsyncTaskExecutor
.
默认情况下,当自定义Executor
bean 已注册,则自动配置的AsyncTaskExecutor
backs off 和自定义的Executor
用于常规任务执行(通过@EnableAsync
).
但是,Spring MVC、Spring WebFlux 和 Spring GraphQL 都需要一个名为applicationTaskExecutor
.
对于 Spring MVC 和 Spring WebFlux,此 bean 的类型必须为AsyncTaskExecutor
,而 Spring GraphQL 不强制执行此类型要求。
Spring WebSocket 和 JPA 将使用AsyncTaskExecutor
如果此类型的单个 Bean 可用,或者名为applicationTaskExecutor
已定义。
最后,的 boostrap 执行程序ApplicationContext
使用名为applicationTaskExecutor
除非名为bootstrapExecutor
已定义。
以下代码片段演示了如何注册自定义AsyncTaskExecutor
与 Spring MVC、Spring WebFlux、Spring GraphQL、Spring WebSocket、JPA 和 bean 的后台初始化一起使用。
-
Java
-
Kotlin
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
@Configuration(proxyBeanMethods = false)
public class MyTaskExecutorConfiguration {
@Bean("applicationTaskExecutor")
SimpleAsyncTaskExecutor applicationTaskExecutor() {
return new SimpleAsyncTaskExecutor("app-");
}
}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.task.SimpleAsyncTaskExecutor
@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {
@Bean("applicationTaskExecutor")
fun applicationTaskExecutor(): SimpleAsyncTaskExecutor {
return SimpleAsyncTaskExecutor("app-")
}
}
这 |
如果 auto-configured |
如果您的应用程序需要多个Executor
用于不同集成的 bean,例如用于常规任务执行的 bean@EnableAsync
其他对于 Spring MVC、Spring WebFlux、Spring WebSocket 和 JPA,您可以按如下方式配置它们。
-
Java
-
Kotlin
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration(proxyBeanMethods = false)
public class MyTaskExecutorConfiguration {
@Bean("applicationTaskExecutor")
SimpleAsyncTaskExecutor applicationTaskExecutor() {
return new SimpleAsyncTaskExecutor("app-");
}
@Bean("taskExecutor")
ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("async-");
return threadPoolTaskExecutor;
}
}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.task.SimpleAsyncTaskExecutor
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {
@Bean("applicationTaskExecutor")
fun applicationTaskExecutor(): SimpleAsyncTaskExecutor {
return SimpleAsyncTaskExecutor("app-")
}
@Bean("taskExecutor")
fun taskExecutor(): ThreadPoolTaskExecutor {
val threadPoolTaskExecutor = ThreadPoolTaskExecutor()
threadPoolTaskExecutor.setThreadNamePrefix("async-")
return threadPoolTaskExecutor
}
}
自动配置的
|
如果taskExecutor
named bean 不是一个选项,您可以将 bean 标记为@Primary
或定义一个AsyncConfigurer
bean 来指定Executor
负责处理常规任务执行@EnableAsync
.
以下示例演示了如何实现此目的。
-
Java
-
Kotlin
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
@Configuration(proxyBeanMethods = false)
public class MyTaskExecutorConfiguration {
@Bean
AsyncConfigurer asyncConfigurer(ExecutorService executorService) {
return new AsyncConfigurer() {
@Override
public Executor getAsyncExecutor() {
return executorService;
}
};
}
@Bean
ExecutorService executorService() {
return Executors.newCachedThreadPool();
}
}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.annotation.AsyncConfigurer
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {
@Bean
fun asyncConfigurer(executorService: ExecutorService): AsyncConfigurer {
return object : AsyncConfigurer {
override fun getAsyncExecutor(): Executor {
return executorService
}
}
}
@Bean
fun executorService(): ExecutorService {
return Executors.newCachedThreadPool()
}
}
注册自定义Executor
同时保持 auto-configuredAsyncTaskExecutor
中,您可以创建自定义Executor
bean 并设置defaultCandidate=false
属性@Bean
注释,如以下示例所示:
-
Java
-
Kotlin
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyTaskExecutorConfiguration {
@Bean(defaultCandidate = false)
@Qualifier("scheduledExecutorService")
ScheduledExecutorService scheduledExecutorService() {
return Executors.newSingleThreadScheduledExecutor();
}
}
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {
@Bean(defaultCandidate = false)
@Qualifier("scheduledExecutorService")
fun scheduledExecutorService(): ScheduledExecutorService {
return Executors.newSingleThreadScheduledExecutor()
}
}
在这种情况下,您将能够自动装配您的自定义Executor
添加到其他组件中,同时保留自动配置的AsyncTaskExecutor
.
但是,请记住使用@Qualifier
注释@Autowired
.
如果无法做到这一点,则可以请求 Spring Boot 自动配置一个AsyncTaskExecutor
总之,如下所示:
-
Properties
-
YAML
spring.task.execution.mode=force
spring:
task:
execution:
mode: force
自动配置的AsyncTaskExecutor
将自动用于所有集成,即使自定义的Executor
Bean 已注册,包括标记为@Primary
.
这些集成包括:
-
异步任务执行 (
@EnableAsync
),除非AsyncConfigurer
Bean 存在。 -
Spring for GraphQL 对
Callable
从 Controller 方法返回值。 -
Spring MVC 的异步请求处理。
-
Spring WebFlux 的阻塞执行支持。
-
用于 Spring WebSocket 中的入站和出站消息通道。
-
JPA 的引导执行程序,基于 JPA 存储库的引导模式。
-
Bootstrap Executor 用于
ApplicationContext
,除非bootstrapExecutor
已定义。
根据您的目标排列方式,您可以设置 |
什么时候 |
当ThreadPoolTaskExecutor
是自动配置的,则线程池使用 8 个核心线程,这些线程可以根据负载进行扩展和收缩。
这些默认设置可以使用spring.task.execution
namespace 中,如以下示例所示:
-
Properties
-
YAML
spring.task.execution.pool.max-size=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s
spring:
task:
execution:
pool:
max-size: 16
queue-capacity: 100
keep-alive: "10s"
这会将线程池更改为使用有界队列,以便在队列已满(100 个任务)时,线程池增加到最多 16 个线程。 池的收缩更加激进,因为线程在空闲 10 秒(而不是默认 60 秒)时被回收。
如果需要将调度程序与计划任务执行相关联(使用@EnableScheduling
例如)。
如果启用了虚拟线程(使用 Java 21+ 和spring.threads.virtual.enabled
设置为true
),这将是一个SimpleAsyncTaskScheduler
使用虚拟线程。
这SimpleAsyncTaskScheduler
将忽略任何与池化相关的属性。
如果未启用虚拟线程,它将是一个ThreadPoolTaskScheduler
具有合理的默认值。
这ThreadPoolTaskScheduler
默认使用一个线程,并且可以使用spring.task.scheduling
namespace 中,如以下示例所示:
-
Properties
-
YAML
spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
spring:
task:
scheduling:
thread-name-prefix: "scheduling-"
pool:
size: 2
一个ThreadPoolTaskExecutorBuilder
bean、一个SimpleAsyncTaskExecutorBuilder
bean、一个ThreadPoolTaskSchedulerBuilder
bean 和SimpleAsyncTaskSchedulerBuilder
在上下文中可用。
这SimpleAsyncTaskExecutorBuilder
和SimpleAsyncTaskSchedulerBuilder
如果启用了 bean,则 bean 会自动配置为使用虚拟线程(使用 Java 21+ 和spring.threads.virtual.enabled
设置为true
).