Task Execution and Scheduling

上下文内不存在 Executor Bean 时,Spring Boot 会自动配置一个 AsyncTaskExecutor 。当启用虚拟线程(使用 Java 21+ 并且将 configprop:spring.threads.virtual.enabled[] 设置为 true)时,它将是使用虚拟线程的 SimpleAsyncTaskExecutor 。否则,它将是具有合理默认值的 ThreadPoolTaskExecutor 。无论哪种情况,都会自动将自动配置的执行程序用于:

  • asynchronous task execution (@EnableAsync)

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

  • Spring MVC 的异步请求处理

  • Spring WebFlux 的阻塞执行支持

如果您已经定义了上下文中自定义的 Executor ,则常规任务执行(也就是 @EnableAsync)和 Spring for GraphQL 都将使用它。不过,如果它是一个 AsyncTaskExecutor 实现(名为 applicationTaskExecutor),则 Spring MVC 和 Spring WebFlux 支持只使用它。根据您的目标安排,您可以将 Executor 更改为 AsyncTaskExecutor ,或者定义一个 AsyncTaskExecutor 和一个 AsyncConfigurer 来包装您自定义的 Executor 。 自动配置的 ThreadPoolTaskExecutorBuilder 允许你轻松地创建实例,这些实例会重现自动配置默认执行的操作。

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

spring:
  task:
    execution:
      pool:
        max-size: 16
        queue-capacity: 100
        keep-alive: "10s"

这更改了线程池,以便使用一个有界队列,因此当队列已满(100 个任务)时,线程池将增加到最多 16 个线程。线程池的缩减会更加激进,因为当线程空闲 10 秒(而不是默认的 60 秒)时,它们会被回收。

也可以自动配置调度程序,如果它需要与计划任务执行(例如,使用 @EnableScheduling)关联的话。

如果启用了虚拟线程(使用 Java 21+ 和将 configprop:spring.threads.virtual.enabled[] 设置为 true),这将是一个使用虚拟线程的 SimpleAsyncTaskScheduler。这个 SimpleAsyncTaskScheduler 将忽略任何与池相关的属性。

如果未启用虚拟线程,它将是一个具有明智默认值的 ThreadPoolTaskScheduler。默认情况下 ThreadPoolTaskScheduler 使用一个线程,并且可以使用 spring.task.scheduling 命名空间来微调其设置,如下例所示:

spring:
  task:
    scheduling:
      thread-name-prefix: "scheduling-"
      pool:
        size: 2

如果需要创建自定义 executor 或调度程序,会在上下文中提供一个 ThreadPoolTaskExecutorBuilder bean、一个 SimpleAsyncTaskExecutorBuilder bean、一个 ThreadPoolTaskSchedulerBuilder bean 和一个 SimpleAsyncTaskSchedulerBuilder。如果启用了虚拟线程,则 SimpleAsyncTaskExecutorBuilderSimpleAsyncTaskSchedulerBuilder bean 会自动配置为使用虚拟线程(使用 Java 21+ 和将 configprop:spring.threads.virtual.enabled[] 设置为 true)。