spring @Scheduled带注释的方法是否在不同的线程上运行?

fro*_*roi 64 java spring scheduled-tasks

我有几个用@Scheduled注释的方法(fixedDelay = 10000).

在应用程序上下文中,我有这个注释驱动设置:

<task:annotation-driven />
Run Code Online (Sandbox Code Playgroud)

问题是,有时一些方法执行会延迟几秒甚至几分钟.

我假设即使方法需要一段时间才能完成执行,其他方法仍然会执行.所以我不明白延迟.

有没有办法可以减少甚至消除延迟?

G. *_*cki 56

为了完整起见,下面的代码显示了使用java config配置调度程序的最简单方法:

@Configuration
@EnableScheduling
public class SpringConfiguration {

    @Bean(destroyMethod = "shutdown")
    public Executor taskScheduler() {
        return Executors.newScheduledThreadPool(5);
    }
    ...
Run Code Online (Sandbox Code Playgroud)

当需要更多控制时,@Configuration可以实现一个类SchedulingConfigurer.

  • 由于`Executor`接口没有`shutdown()`方法,我想最好使用`ExecutorService`作为返回类型来使bean定义正确.或者Spring会在运行时发现实际的bean类型吗? (4认同)
  • 不能与 Spring 自动配置一起工作:***无法注册在类路径资源 [org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class] 中定义的 bean 'taskScheduler'。具有该名称的 bean 已在类路径资源中定义...*** (4认同)
  • XML 配置 - `&lt;task:scheduler id="taskScheduler" pool-size="5"/&gt;` (2认同)
  • 有关 SchedulingConfigurer 的示例,请参见 [此处](/sf/answers/2451230561/) (2认同)

JB *_*zet 48

有关安排文档说:

如果未提供pool-size属性,则默认线程池将只有一个线程.

因此,如果您有许多计划任务,则应该按照文档中的说明配置调度程序,以使池具有更多线程,以确保一个长任务不会延迟所有其他任务.

  • 就像一个假设:只提供一般文档的链接并说你已经"配置它"没有帮助...提供一个例子是无比更有帮助的.我投了g票.Demecki的答案如下,而不是你的答案就是出于这个原因......只是提示取得成功 (19认同)

L.B*_*utz 37

2019 年更新

您还可以在应用程序属性文件中设置一个增加池大小的属性:

spring.task.scheduling.pool.size=10

似乎自 Spring Boot 2.1.0 以来就存在。

  • 如果 Spring Boot 版本 &gt;= 2.0,这是唯一的方法。重写taskScheduler()是没有用的 (4认同)

Sot*_*lis 26

注释的方法@Scheduled意味着在某个时刻在不同的线程上单独运行.

如果您没有TaskScheduler在配置中提供,Spring将使用

Executors.newSingleThreadScheduledExecutor();
Run Code Online (Sandbox Code Playgroud)

返回一个ScheduledExecutorService在单个线程上运行的.因此,如果您有多个@Scheduled方法,虽然它们已被调度,但它们每个都需要等待线程完成执行上一个任务.随着队列填满的速度快于排空,您可能会继续变得越来越大.

确保使用适当数量的线程配置调度环境.

  • 我觉得你太善良了 - 根本不在文档中.至于源代码 - 它可以在发布之间更改. (2认同)

小智 10

您可以使用:

@Bean()
public  ThreadPoolTaskScheduler  taskScheduler(){
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(2);
    return  taskScheduler;
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为在返回您的taskScheduler实例之前,最好先调用taskScheduler.initialize();。 (2认同)

jgr*_*een 9

@EnableScheduling注释提供了关键信息,以及如何解决它:

默认情况下,将搜索关联的调度程序定义:上下文中唯一的 TaskScheduler bean,或否则名为“taskScheduler”的 TaskScheduler bean;还将对 ScheduledExecutorService bean 执行相同的查找。如果两者都不可解析,则将在注册器中创建和使用本地单线程默认调度程序

当需要更多控制时,@Configuration 类可以实现 SchedulingConfigurer。这允许访问底层 ScheduledTaskRegistrar 实例。例如,以下示例演示如何自定义用于执行计划任务的 Executor:

 @Configuration
 @EnableScheduling
 public class AppConfig implements SchedulingConfigurer {

     @Override
     public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
         taskRegistrar.setScheduler(taskExecutor());
     }

     @Bean(destroyMethod="shutdown")
     public Executor taskExecutor() {
         return Executors.newScheduledThreadPool(100);
     }
 }
Run Code Online (Sandbox Code Playgroud)

(强调)