Spring调度任务 - 只运行一次

shx*_*shx 24 java cron spring scheduled-tasks

是否可以在指定的时间仅安排一次Spring服务方法?例如,当前时间是下午2点,但是当我点击操作按钮时,我希望我的服务方法在晚上8点开始.我熟悉@Scheduled注释,我不知道如何编写cron表达式而不是定期运行.这@Scheduled(cron = "0 0 20 * * ?")一天每天晚上8点开火.
有什么建议?

Lau*_* L. 28

您可以使用Spring的TaskScheduler实现之一.我在下面提供了一个示例,其中一个不需要太多配置(ConcurrentTaskScheduler包装单线程预定执行程序).

最简单的方法是一个名为schedule的方法,它只接受Runnable和Date.这将导致任务 指定时间后运行一次.所有其他方法都能够安排任务重复运行.

阅读有关任务执行和计划的更多信息

简单的工作示例:

private TaskScheduler scheduler;

Runnable exampleRunnable = new Runnable(){
    @Override
    public void run() {
        System.out.println("Works");
    }
};

@Async
public void executeTaskT() {
    ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor();
    scheduler = new ConcurrentTaskScheduler(localExecutor);

    scheduler.schedule(exampleRunnable,
            new Date(1432152000000L));//today at 8 pm UTC - replace it with any timestamp in miliseconds to text
}

...

executeTaskT() //call it somewhere after the spring application has been configured
Run Code Online (Sandbox Code Playgroud)

注意:

要启用对@Scheduled和@Async注释的支持,请将@EnableScheduling和@EnableAsync添加到您的@Configuration类之一


更新 - 取消计划任务

TaskScheduler的schedule方法返回ScheduledFuture,这是一个可以取消延迟结果操作.

因此,为了取消它,您需要保留计划任务的句柄(即保留ScheduledFuture返回对象).

更改以上代码以取消任务:

  1. 在executeTaskT方法之外声明ScheduledFuture. __CODE__

  2. 将您的调用修改为schedule以保持返回对象: __CODE__

  3. 在代码中的某处调用scheduledFuture对象取消 __CODE__


小智 22

死人的解决方案:

@Scheduled(ini​​tialDelay = 1000 * 30,fixedDelay = Long.MAX_VALUE)

在再次发射之前,您将已经死亡。

  • 传说是这样给出答案的! (7认同)
  • 如果重新启动应用程序,代码将再次运行:P (6认同)
  • 地球在再次燃烧之前也将被太阳吞噬。 (2认同)

smi*_*hra 5

您可以按如下方式扩展 PeriodicTrigger - 它检查 lastCompletionTime:如果任务以前从未运行过,它将为空。如果您想在某个给定时间只运行一次任务,您可以尝试这种变体。

class RunOnceTrigger extends PeriodicTrigger {
    public RunOnceTrigger(long period) {
        super(period);
        setInitialDelay(period);
    }

    @Override
    public Date nextExecutionTime(TriggerContext triggerContext) {
        if(triggerContext.lastCompletionTime() == null) {   // hasn't executed yet
            return super.nextExecutionTime(triggerContext);
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)