spring-Scheduled

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()方法再次被执行,巧妙。如果不用这种方式实现,还可以怎么实现呢?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,810评论 19 139
  • 博客原文 徒手翻译spring framework 4.2.3官方文档的第33章,若有翻译不当之处请指正。 定时任...
    rabbitGYK阅读 10,993评论 4 24
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 47,118评论 6 342
  • 假期就要进入倒计时了! 出游的就要回家了,睡眠颠倒的要开始倒时差了。当习惯人群拥挤的景点又恢复落寞,当攒了好...
    杉杉妈妈阅读 1,859评论 2 2
  • 前言:是夜,月挂高楼暗,万家灯火明,孤坐窗前醉,只为思子情。 我一个人于窗前久坐,我想着 别人家的灯火, 遥远的地...
    风往哪儿吹阅读 1,828评论 4 9

友情链接更多精彩内容