Spring Task Executor在上一个任务完成之前不会触发

时间:2013-02-22 16:16:24

标签: java spring scheduled-tasks task spring-annotations

我在类中有一个具有@Scheduled注释

的方法
@Scheduled(cron = "* * * * * *")
public void doSomething() {

}

这应该每秒执行一次(假设cron语句正确)。

我将sping配置设置为

<task:scheduler id="taskScheduler" pool-size="2" />
<task:executor id="taskExecutor" pool-size="2" />
<task:annotation-driven executor="taskExecutor" scheduler="taskScheduler" />

问题是在最后一次执行完成之前,该方法不会再次触发。我希望看到它开火两次(并且可能开始在某个地方填写一份工作队列)。

如何删除方法调用之间的依赖关系,但仍然确保一次只运行2个进程。

3 个答案:

答案 0 :(得分:0)

似乎有一种想法是将实际工作交给taskExecutor

@Scheduled(cron = "* * * * * *")
 public void doSomething() {
   this.executor.execute(new Runnable() {...}
 }

然后将拒绝政策添加为* CALLER_RUNS *

<task:scheduler id="taskScheduler" pool-size="1" />
<task:executor id="taskExecutor" pool-size="1"
    queue-capacity="1" rejection-policy="CALLER_RUNS" />
<task:annotation-driven executor="taskExecutor"
    scheduler="taskScheduler" />

所以在上面,工作总是由一个线程池完成。

不确定这是否是你最好的方式。

答案 1 :(得分:0)

由于调度程序线程忙于运行任务,因此不会触发新的执行。

为了实现您要求的行为,请将任务委托给执行程序线程。最简单的方法是使用@Async简单地注释方法。

@Scheduled(cron = "* * * * * *")
@Async
public void doSomething() {
   ...
}

请记住,您必须将任务执行程序池大小调整为所需容量,以便适应并行运行的执行程序线程。

答案 2 :(得分:-1)

您可以尝试将@ScheduledfixedRate - 值一起使用,而不是cronfixedDelay

  

<强>固定利率             在调用之间以固定的周期执行带注释的方法。

     

<强> FIXEDDELAY             在最后一次调用结束和下一次调用开始之间以固定周期执行带注释的方法。

使用 fixedRate ,该方法的另一次执行计划在上次启动之后的一定时间内发生。

使用 fixedDelay ,下一次调用会在上次结束之后的一段时间内发生。

当然,您的线程池必须有另一个空闲线程,以便任务按时运行(如果前一个仍在执行)。