繁体   English   中英

spring boot中的并发调度方法

[英]Concurrent Scheduled method in spring boot

我有一个 spring 应用程序,它有两个用@Component 注释的类,在每个类中,我有一个用@Scheduled 注释的方法,这意味着我想以固定的时间间隔运行这些方法,如下所示:

这是第一个组件,它有一个 readFirstComponent() 方法,这个方法从某个地方读取一些东西并且需要一段时间来执行,@Component public class FirstComp {

@Scheduled(fixedRate = 20000 )
public void readFirstComponent() {
    // body
}

//其他方法 }

第二个组件几乎和第一个组件一样,

@Component

公共类 SecondComp {

@Scheduled(fixedRate = 20000 )
public void readSecondComponent() {
    // body
}

//其他方法 }

我有一个跑步者类来启动应用程序

@SpringBootApplication
@EnableScheduling
@ImportResource("classpath:spring/Spring-AutoScan.xml")
public class Application {
public static void main(final String args[]) {
    SpringApplication.run(Application.class);    
}

}

当我启动应用程序时,FirtComp 正在启动并且 readFirstComponent() 在将近 14 秒结束后执行 THEN readSecondComponent() from SecondComp 正在启动,依此类推,我的问题是我想同时启动这两种方法,请帮助我解决这个问题

默认情况下只有一个线程来运行调度任务。

您可以在此处阅读并了解如何配置调度程序以获取具有更多线程的池。

27.4.1 启用调度注解

要启用对 @Scheduled 和 @Async 注释的支持,请将 @EnableScheduling 和 @EnableAsync 添加到您的 @Configuration 类之一:

@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
}

您可以自由选择应用程序的相关注释。 例如,如果您只需要支持@Scheduled,只需省略@EnableAsync。 对于更细粒度的控制,您可以另外实现 SchedulingConfigurer 和/或 AsyncConfigurer 接口。 有关完整详细信息,请参阅 javadoc。

如果您更喜欢 XML 配置,请使用该元素。

<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>

请注意,上面的 XML 提供了一个执行程序引用来处理那些与带有 @Async 注释的方法相对应的任务,并且提供了调度程序引用来管理那些用 @Scheduled 注释的方法。

由于您使用注释来配置 bean,因此最好implement the SchedulingConfigurer

像这样:

@Configuration
@EnableScheduling
public class SchedulingConfig implements SchedulingConfigurer {

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

@Bean(destroyMethod = "shutdown")
public Executor taskExecutor() {
    return Executors.newScheduledThreadPool(10);
}
}

老问题,但我自己正在处理这个问题。 我无法使用上面提供的解决方案,因为我需要确保每次只运行每个方法的一个实例。 并且增加默认调度线程池大小意味着如果方法花费的时间超过 shcedule 间隔,我最终可能会遇到麻烦。

所以相反我创建了 2 个单线程的线程池,然后对每个方法进行注释以使用相关的线程池(即单线程)。

创建线程池:

@SpringBootApplication
@EnableScheduling
@EnableAsync(proxyTargetClass=true)
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(MainApplication.class);   
        application.run(args);
    }       

    @Bean("schedulePool1")
    public Executor jobPool() {
        ThreadPoolTaskExecutor exec = new ThreadPoolTaskExecutor();
        exec.setCorePoolSize(1);
        exec.setMaxPoolSize(1);
        exec.setQueueCapacity(10);
        exec.setThreadNamePrefix("first-");
        exec.initialize();
        return exec;
    }       

    @Bean("schedulePool2")
    public Executor jobPool2() {
        ThreadPoolTaskExecutor exec = new ThreadPoolTaskExecutor();
        exec.setCorePoolSize(1);
        exec.setMaxPoolSize(1);
        exec.setQueueCapacity(10);
        exec.setThreadNamePrefix("second-");
        exec.initialize();
        return exec;
    }
}

然后,您可以将@Async注释添加到您的两个 sheduled 方法中。

@Async("schedulePool1")
@Scheduled(fixedRate = 20000 )
public void readFirstComponent() {
    // body
}

@Async("schedulePool2")
@Scheduled(fixedRate = 20000 )
public void readSecondComponent() {
    // body
}

然后在您的日志中,您应该看到带有正确[thread]

2020-02-21 20:47:01 [first-1] INFO  sodved.JobSchedule - running readFirstComponent
...
2020-02-21 20:47:01 [second-1] INFO  sodved.JobService - running readSecondComponent

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM