简体   繁体   English

一起使用@Scheduled 和@Async?

[英]using @Scheduled and @Async together?

If i want a method to repeat async, can i use @Scheduled and @Async together ?如果我想要一种重复异步的方法,我可以一起使用 @Scheduled 和 @Async 吗?

@Async
@Scheduled(fixedDelay = x)
public void doSomethingEveryXMinuteAsync() { 
  // action 
}

or is there another standard way to achive this ?还是有另一种标准方法来实现这一目标?

There is no need to use @Async.无需使用@Async。 Just use fixedRate attribute of @Scheduled instead of fixedDelay.只需使用@Scheduled 的fixedRate属性而不是fixedDelay。 Spring will make another invocation on the method after the given time regardless of any call is already being processed. Spring 将在给定时间后对该方法进行另一次调用,而不管是否已经处理了任何调用。

UPDATE:更新:

Apparently fixedRate attribute does not enforce a scheduled method to be called asynchronously and increasing pool size of scheduler task executor only enables asynchronous execution of independent @Scheduled methods.显然,fixedRate 属性不会强制异步调用调度方法,并且增加调度程序任务执行器的池大小只会启用独立 @Scheduled 方法的异步执行。 Even putting @Async on the method does not make it work as OP has asked.即使将 @Async 放在方法上也不能像 OP 所要求的那样工作。

ScheduledAnnotationBeanPostProcessor just creates a Runnable from the @Scheduled method and does not create any pointcut as @Async method processor would. ScheduledAnnotationBeanPostProcessor 只是从 @Scheduled 方法创建一个 Runnable 并且不会像 @Async 方法处理器那样创建任何切入点。 ScheduledThreadPoolExecutor waits until Runnable#run() is finished and sets the next execution time using the start time and the fixed rate. ScheduledThreadPoolExecutor等待直到 Runnable#run() 完成并使用开始时间和固定速率设置下一次执行时间。 So if the method call takes more time than the scheduled time, the next task is triggered right after the previous call is finished.因此,如果方法调用花费的时间比预定时间长,则在前一个调用完成后立即触发下一个任务。

An easy solution would be extracting the actual method into another class as a @Async method and calling this method from the @Scheduled method.一个简单的解决方案是将实际方法作为 @Async 方法提取到另一个类中,并从 @Scheduled 方法调用此方法。

Implement SchedulingConfigurer and override configureTasks method.实现 SchedulingConfigurer 并覆盖 configureTasks 方法。 Define poolsize more than one, It will work as you are expecting.定义多个池大小,它将按您的预期工作。

You should configure implementing SchedulingConfigurer :您应该配置实现SchedulingConfigurer

@Configuration
@EnableScheduling
public class ScheduledConfiguration implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar)
    {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(10);
        threadPoolTaskScheduler.setThreadNamePrefix("your-scheduler-");
        threadPoolTaskScheduler.initialize();

        scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
    }
}

With this code you achieve parallel execution of your method which is annotated with @Scheduled .使用此代码,您可以并行执行用@Scheduled注释的方法。

  1. @Async and @Scheduled method shouldn't be in a same class. @Async@Scheduled方法不应该在同一个类中。
  2. follow the manual and add AsyncConfigurer https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html按照手册并添加 AsyncConfigurer https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html

您还可以设置属性:

spring.task.scheduling.pool.size

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

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