美文网首页
spring-Scheduled

spring-Scheduled

作者: swa19 | 来源:发表于2017-08-27 16:57 被阅读0次

    SpringSchedule配置简单,并且由于属于Spring框架,可以通过Spring来管理bean的生命周期,从而可以降低编程的复杂度。

    SpringSchedule的使用

    以注解配置为例

    1. 配置文件中添加配置
      添加相关注解配置:
    xmlns:task="http://www.springframework.org/schema/task"
    http://www.springframework.org/schema/task  http://www.springframework.org/schema/task/spring-task-3.0.xsd
    

    开启定时任务的注解扫描:
    <task:annotation-driven/>

    1. 为方法添加@Scheduled注解
      设置定时任务的方式有两种,一种是配置一定的延时时间以固定频率运行,一种是设置scon表达式
      xml配置方式也很简单:
      只需在配置文件中添加
    <bean id="myBean" class="BeanClass">
        </bean>
        <task:scheduled-tasks >
            <task:scheduled ref="myBean" method="myMethod" cron="0 0 1 * * ?"/>
        </task:scheduled-tasks>
    

    即可

    代码分析

    diagram.png

    主要类:ScheduledAnnotationBeanPostProcessor
    方法调用链:postProcessAfterInitialization()->processScheduled()->TaskSchedule.schedule()

       A[postProcessAfterInitialization]-->B(postProcessAfterInitialization)
       B-->C{cron?}
       C-->|Y|D[ScheduledTaskRegistrar.scheduleCronTask]
       C-->|N|E[ScheduledTaskRegistrar.scheduleFixedDelayTask]
    

    ScheduledTaskRegistrar.scheduleFixedDelayTask实现比较简单,内部通过TaskScheduler的scheduleAtFixedRate方法实现任务的调度,并返回任务结果
    而ScheduledTaskRegistrar.scheduleCronTask相对来说较复杂,主要看下TaskScheduler的ScheduledFuture<?> schedule(Runnable task, Trigger trigger);方法
    根据以上包的结构图来看,TaskScheduler有六个子类,

    SpringSchedule2.png

    看下ThreadPoolTaskScheduler的schedule方法

    @Override
    public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
    ScheduledExecutorService executor = getScheduledExecutor();
    try {
    ErrorHandler errorHandler = this.errorHandler;
    if (errorHandler == null) {
    errorHandler = TaskUtils.getDefaultErrorHandler(true);
    }
    return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();
    }
    catch (RejectedExecutionException ex) {
    throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
    }
    }
    

    其中的ReschedulingRunnable是一个Runnable的子类,同时也是ScheduledFuture的子类,它的schedule方法如下

    @Nullable
    public ScheduledFuture<?> schedule() {
    synchronized (this.triggerContextMonitor) {
    this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
    if (this.scheduledExecutionTime == null) {
    return null;
    }
    long initialDelay = this.scheduledExecutionTime.getTime() - System.currentTimeMillis();
    this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
    return this;
    }
    }
    

    问题来了,这块代码只看到了执行一次任务,那么后续的任务是怎么触发的?
    this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS),这里的ReschedulingRunnable同时也是一个Runnable类,当执行调度时,其runnable()方法被执行,再看其runnable()方法

    @Override
    public void run() {
    Date actualExecutionTime = new Date();
    super.run();
    Date completionTime = new Date();
    synchronized (this.triggerContextMonitor) {
    Assert.state(this.scheduledExecutionTime != null, "No scheduled execution");
    this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
    if (!obtainCurrentFuture().isCancelled()) {
    schedule();
    }
    }
    }
    

    在runnable()方法中,其schedule()方法再次被执行,巧妙。如果不用这种方式实现,还可以怎么实现呢?

    相关文章

      网友评论

          本文标题: spring-Scheduled

          本文链接:https://www.haomeiwen.com/subject/tefidxtx.html