Spring设置动态定时任务

1.在Spring中经常会用到定时任务,一般会在业务方法上使用@Schedule(cron="定时执行规则"),无法实现从前台动态设置定时任务。

在java中固定频率的任务使用ScheduleExecutorService对象来执行,ScheduleAtFixedRate固定频率执行任务和scheduleWithFixedDelay固定延迟后执行任务。

private static SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    public static void main(String[] args){

     ScheduledExecutorService  scheduleTask= Executors.newScheduledThreadPool(1);

     ScheduledFuture<?> scheduledFuture = scheduleTask.scheduleAtFixedRate(() -> {

      System.out.println("每隔10秒执行一次"+dateFormat.format(new Date()));

     }, 0, 10, TimeUnit.SECONDS);


     scheduleTask.schedule(() -> {

      System.out.println(dateFormat.format(new Date())+"取消定时执行任务");
      scheduledFuture.cancel(true);

     },60,TimeUnit.SECONDS);


    }

在固定频率,每隔10秒执行一次,1分钟后取消任务。

执行结果见下:

在Spring-context中,提供丰富化的ThreadPoolScheduleTask对象和Trigger触发器,可以很方便地设置任务的执行时间。

在trigger中会根据Cron将下一次执行时间,在此次执行后设置,所以如果要动态改变执行时间,需要先取消任务(清空任务BlockQueue)。

根据上次执行时间和cron设置TriggerContext中的执行时间,保证设置与执行的同步一致性。

代码见下:

@Component
public class DynamicScheduledTask {

    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;

    private ScheduledFuture future;

    private static SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    private  String  cron = "";


    public void setCron(final String cron) {
        this.cron = cron;
        stopScheduleTask();

        future=taskScheduler.schedule(new Runnable() {
            @Override
            public void run() {
                // 定时任务的业务逻辑
                System.out.println("动态修改定时任务cron参数,当前时间:" + dateFormat.format(new Date()));
            }
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                // 定时任务触发,可修改定时任务的执行周期
                if ("".equals(cron) || cron == null)
                    return null;
                CronTrigger trigger = new CronTrigger(cron);
                Date nextExecDate =trigger.nextExecutionTime(triggerContext);
                return nextExecDate;
            }});

    }

    public void stopScheduleTask(){

        if(future !=null) {
            future.cancel(true);
        }
    }


}

在这种回调中执行业务任务的方法中,可以看出java的缺陷,并不能将方法作为参数进行传递。在最古老的lisp中宏就可以方法也是一种数据。

在java 1.8中出现函数式编程,用JDK的ScheduleExecutorService使用了函数式,对比发现其实差别并不是很大,只是一种简化。

原文地址:https://www.cnblogs.com/CaesarLinsa/p/8197576.html