简体   繁体   English

如何在 Spring 中运行相同的@Scheduled 方法以多线程启动

[英]How to run the same @Scheduled method in Spring Boot in multiple threads

I currently have a @Scheduled method in my Spring Boot app我目前在我的 Spring Boot 应用程序中有一个 @Scheduled 方法

   @Async
    @Scheduled(fixedDelay = 2000, initialDelay = 1000)
    public void taskA() throws InterruptedException {
        System.out.println("A - " + Thread.currentThread().getName());
    }

My Spring Application file is as follows: @SpringBootApplication我的 Spring 应用文件如下:@SpringBootApplication

@EnableAsync
@EnableScheduling
public class SpringScheduleApplication {

    public static void main(String[] args) {

        SpringApplication.run(SpringScheduleApplication.class, args);
    }


}

I also have a config class set up to establish a thread pool to allow for parallel jobs我还设置了一个配置 class 以建立线程池以允许并行作业

@Configuration
@EnableScheduling
public class SchedulingConfig implements SchedulingConfigurer {
    public static final int NUM_PROCESSING_WORKERS = 10;
    @Override
    public void configureTasks(
            ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(NUM_PROCESSING_WORKERS);
    }
}

When I run the scheduler, I can clearly see the job is picking up in the multiple thread pools.当我运行调度程序时,我可以清楚地看到作业正在多个线程池中进行。

A - pool-1-thread-7
A - pool-1-thread-3
A - pool-1-thread-9
....

Ok..... so here's my problem好的.....所以这是我的问题

What I WANT to do is create multiple instances of taskA and have that run in N amount of threads.我想做的是创建taskA的多个实例并让它在 N 个线程中运行。

I know I can create N amount of methods with the @Scheduled annotation performing the same logic, but this is NOT an acceptable solution.我知道我可以使用@Scheduled注释创建 N 数量的方法来执行相同的逻辑,但这不是一个可接受的解决方案。 This seems very redundant and looks bad, and don't want to copy paste if I add another thread to the pool.这似乎非常多余并且看起来很糟糕,并且如果我向池中添加另一个线程,则不想复制粘贴。 I want to be able to say something like:我希望能够这样说:

for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
  taskA(); // I just want N amount of this tasks existing in parallel.
}

I cannot use anything like Quartz Scheduler because I want to be able to continue to use @Autowired in my project (I can get this behavior to work in Quartz, but setting up @Autowired is a pain and I would like to work with Spring Schedule annotations as much as possible)我不能使用 Quartz Scheduler 之类的东西,因为我希望能够在我的项目中继续使用@Autowired (我可以让这种行为在 Quartz 中工作,但设置 @Autowired 很痛苦,我想使用 Spring Schedule尽可能多的注释)

You already wrote the answer yourself.你已经自己写了答案。 You already have the for loop to use.您已经有了要使用的for循环。 Put the @Scheduled on the method with the for-loop, which calls a taskA method in an external class, and which has the @Async annotation.@Scheduled放在带有for 循环的方法上,该循环调用外部class 中的taskA方法,并且具有@Async注释。


@Autowired
private External external

@Scheduled
public void scheduler() {
  for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
    external.taskA(); // I just want N amount of this tasks existing in parallel.
  }
}
public class External {


  @Async
  public void taskA() { ... }

}

Another solution is to inject the AsyncTaskExecutor into your class that does the scheduling and call submit to execute the task.另一种解决方案是将AsyncTaskExecutor注入您的 class 执行调度并调用submit以执行任务。

@Autowired
private AsyncTaskExecutor taskExecutor;

@Scheduled
public void scheduler() {
  for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
    taskExecutor.submit( () -> taskA());  
  }
}

The advantage of this is that it is more explicit and that your taskA method can be in the same class.这样做的好处是它更明确,并且您的taskA方法可以在同一个 class 中。

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

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