概述

在网站系统里面定时任务是一个重要和不可缺的角色,很多地方需要使用定时执行一项任务。比如,订单系统的接单超时、支付超时,结算系统的定时结算、奖励计算,第三方的认证信息刷新(微信的token),dsp等推广平台数据定时对接,缓存数据的定时更新等。

定时任务实现方式

Timmer定时器

这时最简单和最基础的了,学习过计算机课程的都能知道也都能写。

虽然常见,这里也简单的说几个点:

触发时间点

Timer有两种指定执行时间的方式,一种是给一个时间间隔(Interval),另一种就是给定一个具体的执行时间。

输入图片说明

这时,timer的所有方法,其中画红圈圈的。第一个是在指定的时间点触发,给的参数是一个Date类型;第二个是按照指定的时间间隔触发,给的参数是一个long类型。这两种在实际工程中都是会被用到的。

Timer和TimerTask之间的关系

先看一个最常见的Timer使用示例:

可以看到,一个Timer是可以调度多个Task的,这个也可以从Timer的源代码看出来:

输入图片说明

mainloop循环在不断的读取queue中的task,逐个执行。对于按间隔期不断执行的task,会被计算下次执行时间后被重新放入到队列中。

这里的queue是一个优先级队列,会按照task的执行时间排序,最近的task会被先取出来执行。

输入图片说明

这里想说的是什么呢,在工程中最好不要一个task就创建一个timer,这样有点过于浪费系统资源,因为一个timer就是一个线程,而且在不断的消耗系统的cpu资源。

quartz

quartz是java里面最流行的定时任务调度框架,python里面的定时任务框架APScheduler也是基于Quartz,实现了Quartz的所有功能。

官网教程目录页

以梦为马的个人博客(一个系列的3篇)

quartz的只要构成是schedule、trigger、job三元素的体系,体系中还提供了三者各自的Listener用来监听他们的事件和对事件作出响应。以下是一个最原始的、最基础的quartz使用示例代码(来自官网):

贴在这里,是为了让大家理解三者之间的关系。job封装任务执行的代码,trigger封装任务执行的时间信息,schedule绑定job和trigger执行任务调度。

在java世界里,spring已经是无所不在,接下来简单的看一下spring集成quartz需要做的事情(理解的上述的代码,也就容易理解,为什么spring配置文件里要配置这些东西了)。

1.首先就是要把quartz的包引入进来,添加maven引用:

2.定义job,定义job有两种方式,一种是使用MethodInvokingJobDetailFactoryBean封装自己的bean,这样自己的bean可以是一个任意的pojo;第二种是使用JobDetailFactoryBean,同时让自己的job扩展QuartzJobBean,实现executeInternal的抽象方法。

3.定义trigger 这里可以定义简单的trigger(SimpleTriggerFactoryBean),他使用的是jdk的timer做为调度;也可以定义一个cron表达式类型的trigger(CronTriggerFactoryBean)去定义一个更语义化的触发表达式。

4.定义scheduler,绑定trigger和job

spring-scheduled注解

它不能支持quartz能够支持的集群功能

这里先推荐一个spring的官方版本(如果对spring-scheduled没有概念,需要先查baidu了解一些之后再看这里,因为这个写的比较简洁):http://spring.io/guides/gs/scheduling-tasks/

接下来一块看下scheduled的注解使用,也是两种用法,一个是普通的timer类似调度,一种是cron表达式方式调度。

这里只看cron表达是方式的,普通方式的请见上述网址。以下示例来自于http://howtodoinjava.com/。关于spring-scheduled的使用推荐以下几个网址:

1.引入task命名空间,开启注解自动识别

2.在需要调度的方法上添加@scheduled注解

好了看今天先说到这里,下一篇整理一下quartz基于数据库的集群实现以及elastic-job的使用。最后在给出一篇elastic-job的解析,以及从解析看实际使用场景的实现。

##其它参考资料