如果我想要一种重复异步的方法,我可以同时使用@Scheduled和@Async吗?
@Async
@Scheduled(fixedDelay = x)
public void doSomethingEveryXMinuteAsync() {
// action
}
还是有其他标准的方式来实现这个目标吗?
答案 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)
@Async
和 @Scheduled
方法不应在同一个类中。答案 4 :(得分:0)
您也可以设置属性:
spring.task.scheduling.pool.size