如何 运行 在 Spring 中使用相同的 @Scheduled 方法在多线程中启动
How to run the same @Scheduled method in Spring Boot in multiple threads
我的 Spring 启动应用程序中目前有一个 @Scheduled 方法
@Async
@Scheduled(fixedDelay = 2000, initialDelay = 1000)
public void taskA() throws InterruptedException {
System.out.println("A - " + Thread.currentThread().getName());
}
我的Spring申请文件如下:
@SpringBootApplication
@EnableAsync
@EnableScheduling
public class SpringScheduleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringScheduleApplication.class, args);
}
}
我还设置了一个配置 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);
}
}
当我 运行 调度程序时,我可以清楚地看到作业正在多个线程池中进行。
A - pool-1-thread-7
A - pool-1-thread-3
A - pool-1-thread-9
....
好的.....这是我的问题
我想做的是创建 taskA
的多个实例,并在 N 个线程中拥有 运行。
我知道我可以使用 @Scheduled
注释创建 N 种方法来执行相同的逻辑,但这不是一个可接受的解决方案。这看起来非常多余而且看起来很糟糕,如果我向池中添加另一个线程,我不想复制粘贴。我希望能够说出类似的话:
for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
taskA(); // I just want N amount of this tasks existing in parallel.
}
我不能使用像 Quartz Scheduler 这样的任何东西,因为我希望能够在我的项目中继续使用 @Autowired
(我可以让这种行为在 Quartz 中工作,但是设置 @Autowired 是一件痛苦的事情我想尽可能多地使用 Spring 日程表注释)
你已经自己写了答案。您已经可以使用 for
循环。将 @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() { ... }
}
另一种解决方案是将 AsyncTaskExecutor
注入到执行调度的 class 中,然后调用 submit
来执行任务。
@Autowired
private AsyncTaskExecutor taskExecutor;
@Scheduled
public void scheduler() {
for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
taskExecutor.submit( () -> taskA());
}
}
这样做的好处是更明确,你的taskA
方法可以在同一个class.
我的 Spring 启动应用程序中目前有一个 @Scheduled 方法
@Async
@Scheduled(fixedDelay = 2000, initialDelay = 1000)
public void taskA() throws InterruptedException {
System.out.println("A - " + Thread.currentThread().getName());
}
我的Spring申请文件如下: @SpringBootApplication
@EnableAsync
@EnableScheduling
public class SpringScheduleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringScheduleApplication.class, args);
}
}
我还设置了一个配置 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);
}
}
当我 运行 调度程序时,我可以清楚地看到作业正在多个线程池中进行。
A - pool-1-thread-7
A - pool-1-thread-3
A - pool-1-thread-9
....
好的.....这是我的问题
我想做的是创建 taskA
的多个实例,并在 N 个线程中拥有 运行。
我知道我可以使用 @Scheduled
注释创建 N 种方法来执行相同的逻辑,但这不是一个可接受的解决方案。这看起来非常多余而且看起来很糟糕,如果我向池中添加另一个线程,我不想复制粘贴。我希望能够说出类似的话:
for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
taskA(); // I just want N amount of this tasks existing in parallel.
}
我不能使用像 Quartz Scheduler 这样的任何东西,因为我希望能够在我的项目中继续使用 @Autowired
(我可以让这种行为在 Quartz 中工作,但是设置 @Autowired 是一件痛苦的事情我想尽可能多地使用 Spring 日程表注释)
你已经自己写了答案。您已经可以使用 for
循环。将 @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() { ... }
}
另一种解决方案是将 AsyncTaskExecutor
注入到执行调度的 class 中,然后调用 submit
来执行任务。
@Autowired
private AsyncTaskExecutor taskExecutor;
@Scheduled
public void scheduler() {
for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
taskExecutor.submit( () -> taskA());
}
}
这样做的好处是更明确,你的taskA
方法可以在同一个class.