定时任务之Timer,Quartz,Spring task
来源:互联网 发布:神话网络电话卡骗局 编辑:程序博客网 时间:2024/05/29 18:33
定时任务可以通过三种方式实现:
1.Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。
2.使用Quartz,这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂
3.Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多
- 一Timer
- 二Quartz
- 1作业类继承自特定的基类orgspringframeworkschedulingquartzQuartzJobBean
- a定义作业类需要继承QuartzJobBean
- b 在Spring配置文件中配置作业类
- c配置触发器调用作业类
- d配置调度工厂
- 2作业类不继承特定基类
- a定义作业类
- bSpring中配置作业类
- 1作业类继承自特定的基类orgspringframeworkschedulingquartzQuartzJobBean
- 三Spring-Task
- 1配置文件方式
- a定义作业类
- b在Spring配置文件中配置作业类
- 2注解方式
- 1配置文件方式
- 四Cron表达式详解
- 五定时任务在HAP中的使用
- 1首先继承AbstractJob类然后重写safeExecute 方法
- 2然后在界面配置触发器
- 简单任务
- CRON任务
一、Timer
在java中一个完整定时任务需要由Timer、TimerTask两个类来配合完成。 API中是这样定义他们的,Timer:一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。由TimerTask:Timer 安排为一次执行或重复执行的任务。我们可以这样理解Timer是一种定时器工具,用来在一个后台线程计划执行指定任务,而TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务。
当程序初始化完成Timer后,定时任务就会按照我们设定的时间去执行,Timer提供了schedule方法,该方法有多中重载方式来适应不同的情况,如下:
schedule(TimerTask task, Date time):安排在指定的时间执行指定的任务。schedule(TimerTask task, Date firstTime, long period) :安排指定的任务在指定的时间开始进行重复的固定延迟执行。schedule(TimerTask task, long delay) :安排在指定延迟后执行指定的任务。schedule(TimerTask task, long delay, long period) :安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
同时也重载了scheduleAtFixedRate方法,scheduleAtFixedRate方法与schedule相同,只不过他们的侧重点不同,区别后面分析。
scheduleAtFixedRate(TimerTask task, Date firstTime, long period):安排指定的任务在指定的时间开始进行重复的固定速率执行。scheduleAtFixedRate(TimerTask task, long delay, long period):安排指定的任务在指定的延迟后开始进行重复的固定速率执行。
指定延迟时间执行定时任务:
public class TimerTest01 { Timer timer; public TimerTest01(int time){ timer = new Timer(); timer.schedule(new TimerTaskTest01(), time * 1000); //调用TimerTaskTest01类 } public static void main(String[] args) { System.out.println("timer begin...."); new TimerTest01(3); //三秒后执行TimerTaskTest01中的run方法。 } } public class TimerTaskTest01 extends TimerTask{ public void run() { System.out.println("Time's up!!!!"); } }
打印结果:
首先打印:timer begin.... 3秒后打印:Time's up!!!!
设置schedule中的方法指定定时任务的循环时间和开始时间。
二、Quartz
Quartz是一个任务调度框架,可以指定定时任务开始时间,也可以指定按照某个频度执行。
从作业类的继承方式来讲,可以分为两类:
A. 作业类需要继承自特定的作业类基类,
如Quartz中需要继承自org.springframework.scheduling.quartz.QuartzJobBean;
java.util.Timer中需要继承自java.util.TimerTask。
B. 作业类即普通的java类,不需要继承自任何基类。
下边从作业类和配置文件来详细介绍定时任务是如何实现的:
1)作业类继承自特定的基类:org.springframework.scheduling.quartz.QuartzJobBean
a.定义作业类,需要继承QuartzJobBean
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; public class Job1 extends QuartzJobBean { private int timeout; private static int i = 0; //调度工厂实例化后,经过timeout时间开始执行调度 public void setTimeout(int timeout) { this.timeout = timeout; } /** * 要调度的具体任务 */ @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { System.out.println("定时任务执行中…"); } }
b. 在Spring配置文件中配置作业类
org.springframework.scheduling.quartz.JobDetailBean有两个属性,jobClass属性即我们在java代码中定义的作业类,jobDataAsMap属性即该作业类中需要注入的属性值。
<bean name="job1" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="com.gy.Job1" /> <property name="jobDataAsMap"> <map> <entry key="timeout" value="0" /> </map> </property> </bean>
c.配置触发器,调用作业类
Quartz的作业触发器有两种,分别是
org.springframework.scheduling.quartz.SimpleTriggerBean
org.springframework.scheduling.quartz.CronTriggerBean
SimpleTriggerBean,只支持按照一定频度调用任务,如每隔30分钟运行一次。
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="job1" /> <!-- 触发spring配置的bean --> <property name="startDelay" value="0" /> <!-- 调度工厂实例化后,经过0秒开始执行调度 --> <property name="repeatInterval" value="2000" /><!-- 每2秒调度一次 此处以毫秒为单位--> </bean>
ronTriggerBean,支持到指定时间运行一次,如每天12:00运行一次等。具体Cron表达式后续讲解。
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="job1" /> <property name="cronExpression" value="0 0 12 * * ?" /> <!-— 每天12:00运行一次 --> </bean>
d.配置调度工厂
bean=”cronTrigger” 该参数指定的就是之前配置的触发器的名字。
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger" /> </list> </property> </bean>
2)作业类不继承特定基类
Spring能够支持这种方式,是因为以下两个类分别对应spring支持的两种实现任务调度的方式
org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean:此时我们只使用这个类,使用该类的好处是,我们的任务类不再需要继承自任何类,而是普通的dto。
a.定义作业类
不需要继承任何类
public class Job2 { public void doJob2() { System.out.println("不继承QuartzJobBean方式-调度进行中..."); } }
b.Spring中配置作业类
MethodInvokingJobDetailFactoryBean,有两个关键属性:targetObject指定任务类,targetMethod指定运行的方法。
<bean id="job2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <bean class="com.gy.Job2" /> </property> <property name="targetMethod" value="doJob2" /> <property name="concurrent" value="false" /><!-- 作业不并发调度 --> </bean>
配置触发器和调度工厂和上一部分是一样的,可以参考。
采用Quartz时,需要导入相应的spring的包与Quartz的包。
三、Spring-Task
spring task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包,而且支持注解和配置文件两种,下边详细介绍:
1)配置文件方式
a.定义作业类
import org.springframework.stereotype.Service; @Service public class TaskJob { public void job1() { System.out.println(“任务进行中。。。”); } }
b.在Spring配置文件中配置作业类
在spring配置文件头中添加命名空间及描述
ref=”taskJob” 参数指定的即任务类,method指定的即需要运行的方法。
base-package=” com.gy.mytask ” spring扫描注解。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:task="http://www.springframework.org/schema/task" 。。。。。。 xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> 。。。。 <task:scheduled-tasks> <task:scheduled ref="taskJob" method="job1" cron="0 * * * * ?"/> </task:scheduled-tasks> <context:component-scan base-package=" com.gy.mytask " />
2)注解方式
在方法上使用注解@Scheduled来执行定时任务
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component(“taskJob”) public class TaskJob { @Scheduled(cron = "0 0 3 * * ?") public void job1() { System.out.println(“任务进行中。。。”); } }
但是我们也需要在配置文件中进行相关配置,只要这样Spring才能识别注解@Scheduled
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" default-lazy-init="false"> <context:annotation-config /> <!—spring扫描注解的配置 --> <context:component-scan base-package="com.gy.mytask" /> <!—开启这个配置,spring才能识别@Scheduled注解 --> <task:annotation-driven scheduler="qbScheduler" mode="proxy"/> <task:scheduler id="qbScheduler" pool-size="10"/>
四、Cron表达式详解
在spring 4.x中已经不支持7个参数的cronin表达式了,要求必须是6个参数(具体哪个参数后面会说)。cron表达式的格式如下:
{秒} {分} {时} {日期(具体哪天)} {月} {星期}
秒:必填项,允许的值范围是0-59,支持的特殊符号包括
,
-
*
/
,,
表示特定的某一秒才会触发任务,-
表示一段时间内会触发任务,*
表示每一秒都会触发,/
表示从哪一个时刻开始,每隔多长时间触发一次任务。分:必填项,允许的值范围是0-59,支持的特殊符号和秒一样,含义类推
时:必填项,允许的值范围是0-23,支持的特殊符号和秒一样,含义类推
日期:必填项,允许的值范围是1-31,支持的特殊符号相比秒多了
?
,表示与{星期}互斥,即意味着若明确指定{星期}触发,则表示{日期}无意义,以免引起冲突和混乱。月:必填项,允许的值范围是1-12(JAN-DEC),支持的特殊符号与秒一样,含义类推
星期:必填项,允许值范围是1~7 (SUN-SAT),1代表星期天(一星期的第一天),以此类推,7代表星期六,支持的符号相比秒多了
?
,表达的含义是与{日期}互斥,即意味着若明确指定{日期}触发,则表示{星期}无意义。<!-- 每15秒、30秒、45秒时触发任务 --><task:scheduled ref="app" method="execute6" cron="15,30,45 * * * * ?"/><!-- 15秒到45秒每隔1秒触发任务 --><task:scheduled ref="app" method="execute7" cron="15-45 * * * * ?"/><!-- 每分钟的每15秒时任务任务,每隔5秒触发一次 --><task:scheduled ref="app" method="execute8" cron="15/5 * * * * ?"/><!-- 每分钟的15到30秒之间开始触发,每隔5秒触发一次 --><task:scheduled ref="app" method="execute9" cron="15-30/5 * * * * ?"/><!-- 每小时的0分0秒开始触发,每隔3分钟触发一次 --><task:scheduled ref="app" method="execute10" cron="0 0/3 * * * ?"/><!-- 星期一到星期五的10点15分0秒触发任务 --><task:scheduled ref="app" method="execute11" cron="0 15 10 ? * MON-FRI"/>
如果Cron表达式掌握的不是很好,可以借助Cron在线生成器,自动生成。
具体地址:http://cron.qqe2.com/
五、定时任务在HAP中的使用
HAP封装了一个AbstractJob,我们使用的时候只需要继承AbstractJob然后在safeExecute()方法中加上一些逻辑就可以使用,具体的执行时间和频度可以在界面上配置。
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.hand.hap.job;import org.apache.commons.lang.StringUtils;import org.apache.commons.lang.exception.ExceptionUtils;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.JobListener;import org.quartz.SchedulerException;public abstract class AbstractJob implements Job, JobListener { public static final String JOB_RUNNING_INFO_ID = "JOB_RUNNING_INFO_ID"; private String executionSummary; public AbstractJob() { } public final void execute(JobExecutionContext context) throws JobExecutionException { try { this.safeExecute(context); } catch (Exception var6) { if (StringUtils.isEmpty(this.getExecutionSummary())) { this.setExecutionSummary(ExceptionUtils.getRootCauseMessage(var6)); } JobExecutionException e2 = new JobExecutionException(var6); if (this.isRefireImmediatelyWhenException()) { e2.setRefireImmediately(true); } else { try { context.getScheduler().pauseTrigger(context.getTrigger().getKey()); } catch (SchedulerException var5) { var5.printStackTrace(); } } throw e2; } } //在此方法中写具体的业务逻辑 public abstract void safeExecute(JobExecutionContext var1) throws Exception; protected boolean isRefireImmediatelyWhenException() { return false; } public String getExecutionSummary() { return this.executionSummary; } public void setExecutionSummary(String executionSummary) { this.executionSummary = executionSummary; } public String getName() { return null; } public void jobToBeExecuted(JobExecutionContext jobExecutionContext) { } public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {} public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) { }}
以工作流自动提交为例:
1)首先继承AbstractJob类,然后重写safeExecute() 方法
/** * @description 工作流自动提交 * @author yujiao.liu@hand-china.com * @date 2017/10/19 */@Service@Transactional(rollbackFor = Exception.class)public class SubmitServiceImpl extends AbstractJob { @Override public void safeExecute(JobExecutionContext jobExecutionContext) throws Exception { gxpAutoSubmit("GXP_ITEM"); //物料工作流提交 gxpAutoSubmit("GXP_VENDOR"); //供应商工作流提交 gxpAutoSubmit("GXP_CUSTOMER"); //客户工作流提交 } 。。。}
2)然后在界面配置触发器。
Quartz的作业触发器有两种,分别是
org.springframework.scheduling.quartz.SimpleTriggerBean
org.springframework.scheduling.quartz.CronTriggerBean
CronTrigger能处理更加复杂的时间表达格式,它的使用范围更大。因此在任务明细界面中,分为简单任务和CRON任务。
简单任务:
任务类名:定时任务任务的类名,唯一标示
重复间隔:每次执行定时任务的间隔时间,以秒s 为单位。
重复次数:执行定时任务的重复次数(如果不填重复次数,代表无限循环,按照执行间隔时间执行)
如下图所示,预警测试从2017-10-28 18:53:04 开始,每6分钟执行一次。
CRON任务:
以工作流批量提交为例,通过Cron表达式设置任务的执行频度
如下图所示,批量提交任务每小时的0分开始,时间间隔30分钟。
其中执行记录可以在该界面查看。
如果对于一个任务有特殊需求,可以在任务明细界面点击操作按钮,对任务暂停、恢复、或者删除。
- 定时任务之Timer,Quartz,Spring task
- JAVA定时任务Timer、Spring Task、Quartz
- Java之旅--定时任务(Timer、Quartz、Spring、LinuxCron)
- Java之旅--定时任务(Timer、Quartz、Spring、LinuxCron)
- Java之旅--定时任务(Timer、Quartz、Spring、LinuxCron)
- spring Quartz和 Spring Task定时任务
- Java定时任务(Timer、Quartz、Spring、LinuxCron)
- spring Quartz与Timer定时任务
- spring中quartz和task定时任务
- quartz springh和 spring-task 定时任务
- 【Spring】Quartz和Task实现定时任务
- 定时任务Quartz和spring task
- 理解spring任务调度timer,Quartz,spring task
- Spring定时任务之quartz
- spring定时任务之quartz
- spring定时任务之quartz
- spring定时任务之quartz
- spring定时任务之quartz
- ubuntu16.04 下 多opencv版本安装(3.0.0和3.3.0)
- Java的 面向对象 (类和对象的关系)
- c++ string 标准模板类
- thinkphp模板输出变量使用一个或多个函数
- nginx集群相关
- 定时任务之Timer,Quartz,Spring task
- Golang小项目----Agenda
- 学习java应该如何理解反射
- 【Android动画】仿淘宝加入购物车动画实现
- Redis和MySQL数据同步及Redis使用场景
- Pangolin install
- WinJS中的System.Text.Encoding
- Endnote x7在word 2013中插件不显示
- mac下更改配置文件.bash_profile && Mac上启动mysql初始化账号密码