如何在运行时更改Spring的@Scheduled fixedDelay

jsf*_*jsf 27 java spring scheduled-tasks quartz-scheduler

我需要以固定的间隔运行批处理作业,并能够在运行时更改此批处理作业的时间.为此,我遇到了Spring框架下提供的@Scheduled注释.但我不确定如何在运行时更改fixedDelay的值.我做了一些谷歌搜索,但没有找到任何有用的东西.

Boh*_*ian 49

在spring boot中,您可以直接使用应用程序属性!

例如:

@Scheduled(fixedDelayString = "${my.property.fixed.delay.seconds}000")
private void process() {
    // your impl here
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果未定义属性,您也可以使用默认值,例如,默认值为"60"(秒):

@Scheduled(fixedDelayString = "${my.property.fixed.delay.seconds:60}000")
Run Code Online (Sandbox Code Playgroud)

我发现的其他事情:

  • 该方法必须无效
  • 该方法必须没有参数
  • 方法可能是 private

我发现能够使用private可见性并以这种方式使用它:

@Service
public class MyService {
    public void process() {
        // do something
    }

    @Scheduled(fixedDelayString = "${my.poll.fixed.delay.seconds}000")
    private void autoProcess() {
        process();
    }
}
Run Code Online (Sandbox Code Playgroud)

因为private,预定的方法可以是您的服​​务的本地方法,而不是您的服务API的一部分.

此外,此方法允许process()方法返回值,@Scheduled方法可能不会.例如,您的process()方法可能如下所示:

public ProcessResult process() {
    // do something and collect information about what was done
    return processResult; 
}
Run Code Online (Sandbox Code Playgroud)

提供有关处理过程中发生的事情的一些信息.

  • 这不是一个有用的答案.OP要求"在运行时",你的解决方案需要重启吗? (14认同)
  • @Bohemain感谢您的解决方案,但是如何在运行时更新fixedDelay? (2认同)

ach*_*ach 25

您可以使用a Trigger动态设置下一个执行时间.在这里看到我的答案:

以编程方式使用Spring调度作业(动态设置fixedRate)


Sag*_*uja 8

您也可以为此使用 Spring 表达式语言 (SpEL)。

@Scheduled(fixedDelayString = "#{@applicationPropertyService.getApplicationProperty()}")
public void getSchedule(){
   System.out.println("in scheduled job");
}

@Service
public class ApplicationPropertyService {

    public String getApplicationProperty(){
        //get your value here
        return "5000";
    }
}
Run Code Online (Sandbox Code Playgroud)


gre*_*rep 7

创建接口,类似于:

    public abstract class DynamicSchedule{
        /**
         * Delays scheduler
         * @param milliseconds - the time to delay scheduler.
         */
        abstract void delay(Long milliseconds);

        /**
         * Decreases delay period
         * @param milliseconds - the time to decrease delay period.
         */
        abstract void decreaseDelayInterval(Long milliseconds);

        /**
         * Increases delay period
         * @param milliseconds - the time to increase dela period
        */
        abstract void increaseDelayInterval(Long milliseconds);
}
Run Code Online (Sandbox Code Playgroud)

接下来,让我们在spring-context项目中实现位于org.springframework.scheduling的Trigger接口.

import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;

import java.util.Date;
import java.util.concurrent.ScheduledFuture;

public class CustomDynamicSchedule extends DynamicSchedule implements Trigger {

    private TaskScheduler taskScheduler;
    private ScheduledFuture<?> schedulerFuture;

    /**
     * milliseconds
     */
    private long delayInterval;

    public CustomDynamicSchedule(TaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
    }


    @Override
    public void increaseDelayInterval(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval += delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public void decreaseDelayInterval(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval -= delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public void delay(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval = delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public Date nextExecutionTime(TriggerContext triggerContext) {
        Date lastTime = triggerContext.lastActualExecutionTime();
        return (lastTime == null) ? new Date() : new Date(lastTime.getTime() + delayInterval);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在配置:

@Configuration
public class DynamicSchedulerConfig {
    @Bean
    public CustomDynamicSchedule getDynamicScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.initialize();
        return  new CustomDynamicSchedule(threadPoolTaskScheduler);
    }
}
Run Code Online (Sandbox Code Playgroud)

和用法:

@EnableScheduling
@Component
public class TestSchedulerComponent {

    @Autowired
    private CustomDynamicSchedule dynamicSchedule;

    @Scheduled(fixedDelay = 5000)
    public void testMethod() {
        dynamicSchedule.delay(1000l);
        dynamicSchedule.increaseDelayInterval(9000l);
        dynamicSchedule.decreaseDelayInterval(5000l);
    }

}
Run Code Online (Sandbox Code Playgroud)