任务执行与调度

在上下文中没有 Executor bean 的情况下,Spring Boot 会自动配置一个 AsyncTaskExecutor。当启用虚拟线程时(使用 Java 21+ 并将 spring.threads.virtual.enabled 设置为 true),这将是一个使用虚拟线程的 SimpleAsyncTaskExecutor。否则,它将是一个具有合理默认设置的 ThreadPoolTaskExecutor。在这两种情况下,自动配置的执行器都会自动用于以下场景:

  • 异步任务执行(@EnableAsync

  • Spring for GraphQL 对控制器方法中 Callable 返回值的异步处理

  • Spring MVC 的异步请求处理

  • Spring WebFlux 的阻塞执行支持

如果你在上下文中定义了自定义的 Executor,那么常规任务执行(即 @EnableAsync)和 Spring for GraphQL 都会使用它。然而,Spring MVC 和 Spring WebFlux 的支持只有当它是一个 AsyncTaskExecutor 实现(命名为 applicationTaskExecutor)时才会使用它。根据你的目标配置,你可以将你的 Executor 更改为一个 AsyncTaskExecutor,或者定义一个 AsyncTaskExecutor 和一个包装你的自定义 ExecutorAsyncConfigurer

自动配置的 ThreadPoolTaskExecutorBuilder 允许你轻松创建实例,这些实例能够重现自动配置的默认行为。

如果定义了多个 Executor bean,常规任务执行会回退到名为 taskExecutor 的 bean。GraphQL、Spring MVC 和 Spring WebFlux 的支持会回退到名为 applicationTaskExecutor 的 bean。

当自动配置 ThreadPoolTaskExecutor 时,线程池使用 8 个核心线程,这些线程可以根据负载增长和收缩。可以使用 spring.task.execution 命名空间来微调这些默认设置,如下例所示:

  • 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 将忽略任何与池化相关的属性。

如果未启用虚拟线程,它将是一个具有合理默认设置的 ThreadPoolTaskSchedulerThreadPoolTaskScheduler 默认使用一个线程,可以使用 spring.task.scheduling 命名空间对其设置进行微调,如下例所示:

  • 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 bean。如果启用了虚拟线程(使用 Java 21+ 并将 spring.threads.virtual.enabled 设置为 true),SimpleAsyncTaskExecutorBuilderSimpleAsyncTaskSchedulerBuilder bean 将被自动配置为使用虚拟线程。