如何配置spring来执行重叠的fixedRate任务?

时间:2015-05-18 21:42:13

标签: java multithreading spring

我正在尝试使用java spring中的@Scheduled注释以固定速率执行任务。但是,默认情况下,如果任务比速率慢,spring将不会以固定速率执行fixedRate任务。是否有一些设置我可以添加到我的弹簧配置来改变这种行为?

示例

[int][String]$data[-2][30]
# or
[int]::Parse($data[-2][30])

我有解决方案,但似乎不太理想。基本上,我只是用线程池替换默认的单线程执行器,然后我有一个调度方法调用异步方法,因为@Async注释允许并发执行:

@Service
public class MyTask{
    @Scheduled(fixedRate = 1000)
    public void doIt(){
        // this sometimes takes >1000ms, in which case the next execution is late
        ...
    }
}

我的真实场景的详细信息:在我的生产代码中,我的任务需要10毫秒到10分钟,具体取决于当前的工作负载。理想情况下,我想每隔1000毫秒从池中捕获一个新线程,以便并发线程数随工作负载而增加。显然,我有一个上限(在其他控件中),以防止事情失控。

2 个答案:

答案 0 :(得分:3)

TaskScheduler API(支持一些Spring Scheduling行为)似乎被定义为阻止您请求的行为

  

安排给定的Runnable,在指定的执行时调用它   时间和随后的给定时期。

     

<强>参数

     
      
  • 期间任务连续执行之间的间隔(以毫秒为单位)
  •   

随后后续似乎表明下一次执行只会在当前执行完成后发生。

还有什么,ScheduledExecutorService#scheduleAtFixedRate(..)(内置的TaskScheduler实现使用的)也说

  

如果此任务的执行时间超过其周期,那么   后续执行可能会延迟,但不会同时执行   执行

因此,实现的另一层可以阻止您想要的行为。

一个可能的解决方案,我不推荐使用的解决方案,因为API似乎不是围绕它构建的,而是定义并提供自己同时运行任务的TaskScheduler。请查看@EnableSchedulingSchedulingConfigurer,了解如何注册TaskScheduler

答案 1 :(得分:1)

到目前为止,我发现的最佳解决方案是简单地使用委托来使方法调用异步。这是唯一的选择,因为它允许我在与执行工作的方法相同的类中声明日程表:

@Service
public class AsyncRunner {
    @Async
    public void run(Runnable runnable) {
        runnable.run();
    }
}

@Service
public class MyTask{
    ...
    @Scheduled(fixedRate = 1000)
    public void scheduleIt(){
        asyncRunner.run(this::doIt);
    }
    public void doIt(){
        // this sometimes takes >1000ms, but the next execution is on time
        ...
    }
}