一起使用@Scheduled和@Async?

时间:2017-02-27 10:06:39

标签: java asynchronous spring-boot scheduled-tasks

如果我想要一种重复异步的方法,我可以同时使用@Scheduled和@Async吗?

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

还是有其他标准的方式来实现这个目标吗?

5 个答案:

答案 0 :(得分:3)

无需使用@Async。只需使用@Scheduled的fixedRate属性而不是fixedDelay。无论是否已经处理任何调用,Spring都会在给定时间后对该方法进行另一次调用。

<强>更新

显然,fixedRate属性不会强制执行异步调用的调度方法,并且增加调度程序任务执行程序的池大小只能实现独立的@Scheduled方法的异步执行。即使在方法上放置@Async也不会像OP所要求的那样使它工作。

ScheduledAnnotationBeanPostProcessor只是从@Scheduled方法创建一个Runnable,并且不会像@Async方法处理器那样创建任何切入点。 ScheduledThreadPoolExecutor 等待Runnable#run()完成,并使用开始时间和固定速率设置下一个执行时间。因此,如果方法调用花费的时间超过预定时间,则在上一次调用完成后立即触发下一个任务。

一个简单的解决方案是将实际方法作为@Async方法提取到另一个类中,并从@Scheduled方法调用此方法。

答案 1 :(得分:2)

实施SchedulingConfigurer并重写configureTasks方法。 定义poolsize大于一个,它将按预期工作。

答案 2 :(得分:0)

您应该配置实现 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);
    }
}

使用此代码,您可以并行执行使用 @Scheduled 注释的方法。

答案 3 :(得分:0)

  1. @Async@Scheduled 方法不应在同一个类中。
  2. 按照手册添加 AsyncConfigurerhttps://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html

答案 4 :(得分:0)

您也可以设置属性:

spring.task.scheduling.pool.size