Spring task -- 定時任務(wù)源碼解析

Task定時器

定義xml定時任務(wù)配置

<task:scheduler id="scheduler" pool-size="3" />
<bean id="task" class="task.Task"/>
<task:scheduled-tasks scheduler="scheduler">
    <task:scheduled ref="task" method="print" cron="0/5 * * * * ?"/>
</task:scheduled-tasks>
  • 配置好xml后,Spring將其解析成為BeanDefinition

其中task:scheduled標(biāo)簽被解析為一個Task的具體實(shí)現(xiàn)類

Spring-Task結(jié)構(gòu)圖.png

調(diào)度執(zhí)行入口:ContextLifecycleScheduledTaskRegistrar

    // ContextLifecycleScheduledTaskRegistrar
    // 在Bean初始化之后調(diào)度
    @Override
    public void afterSingletonsInstantiated() {
        scheduleTasks();
    }

    // ScheduledTaskRegistrar
    // 如果配置了相應(yīng)的Tasks,則添加到Set<ScheduledTask> scheduledTasks中
        protected void scheduleTasks() {
        // 初始化taskScheduler,如果沒有配置task:scheduler,就會進(jìn)行初始化
        if (this.taskScheduler == null) {
            this.localExecutor = Executors.newSingleThreadScheduledExecutor();
            this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
        }
        if (this.triggerTasks != null) {
            for (TriggerTask task : this.triggerTasks) {
                addScheduledTask(scheduleTriggerTask(task));
            }
        }
        if (this.cronTasks != null) {
            for (CronTask task : this.cronTasks) {
                addScheduledTask(scheduleCronTask(task));
            }
        }
        if (this.fixedRateTasks != null) {
            for (IntervalTask task : this.fixedRateTasks) {
                addScheduledTask(scheduleFixedRateTask(task));
            }
        }
        if (this.fixedDelayTasks != null) {
            for (IntervalTask task : this.fixedDelayTasks) {
                addScheduledTask(scheduleFixedDelayTask(task));
            }
        }
    }

下面以CronTask為例:

CronTask解析表達(dá)式為trigger
  • tips: Trigger被定義為決定一個任務(wù)的下一次執(zhí)行時間
    /**
     * Create a new {@code CronTask}.
     * @param runnable the underlying task to execute
     * @param expression the cron expression defining when the task should be executed
     */
    public CronTask(Runnable runnable, String expression) {
        this(runnable, new CronTrigger(expression));
    }

    /**
     * Build a {@link CronTrigger} from the pattern provided in the default time zone.
     * @param expression a space-separated list of time fields, following cron
     * expression conventions
     */
    public CronTrigger(String expression) {
        this.sequenceGenerator = new CronSequenceGenerator(expression);
    }

    ···
    // 最后到CronSequenceGenerator進(jìn)行解析
    private void doParse(String[] fields) {
        setNumberHits(this.seconds, fields[0], 0, 60);
        setNumberHits(this.minutes, fields[1], 0, 60);
        setNumberHits(this.hours, fields[2], 0, 24);
        setDaysOfMonth(this.daysOfMonth, fields[3]);
        setMonths(this.months, fields[4]);
        setDays(this.daysOfWeek, replaceOrdinals(fields[5], "SUN,MON,TUE,WED,THU,FRI,SAT"), 8);

        if (this.daysOfWeek.get(7)) {
            // Sunday can be represented as 0 or 7
            this.daysOfWeek.set(0);
            this.daysOfWeek.clear(7);
        }
    }

通過ReschedulingRunnable來完成調(diào)度;

  • (這里不談EnterpriseConcurrentTriggerScheduler)
ReschedulingRunnable: 其父類DelegatingErrorHandlingRunnable implements 了 Runnable
    @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);
            // 下一次執(zhí)行窗口調(diào)用this(ReschedulingRunnable)
            return this;
        }
    }

    @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();
            }
        }
    }

參考:

Seaswalker的Spring-analysis:
github地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容