每当我们想在项目中定期去执行或者重复执行某一个操作,定时这个字眼总会自觉不自觉的浮现在脑海里。当我们并不熟悉任何定时器的时候,我们可能会选择使用线程来完成这个工作:
<span style="font-size:18px;">package org.ysc.action
public class FinanceAction extends Thread{
private Date date;
public void run{
try{
while(true){
Thread.sleep((int)(Math.random()*1000));
date = new Date();
//定时执行任务
}
}catch(Exception e){
e.printStackTrace();
}
}
}</span>
但是如果我们的定时器实现不好,将会使定时器占用系统中的过多内存,给系统造成性能问题,所以在执行定时或者重复的任务,线程并不是最好的选择;
java中常用的定时器
1).使用java.util.Timer 来实现
2).Quartz这个开源的调度框架
➷ Timer的具体实现
使用Timer定义一个定时任务主要分为两个步骤:
1. 创建定时任务类:
<span style="font-size:18px;">package org.ysc.action
import java.util.TimeTask
public class MyTimeTask extends TimeTask{
public void run(){
//要执行的定时任务
}
}</span>
2. 运行定时任务:
2.1 程序直接启动
<span style="font-size:18px;">package org.ysc.action
public class Testmain{
.......
public void run(){
//执行定时器的任务
//创建实例
Timer timer = new Timer();
参数:
new MyTimeTask()- 所要安排的任务。
0- 执行任务前的延迟时间,单位是毫秒。
1*1000- 执行各后续任务之间的时间间隔,单位是毫秒。
timer.schedule(new MyTimeTask(),0,1*1000);
}
}</span>
2.2 web监听的方式
web.xml的配置
<span style="font-size:18px;"><listener>
<listener-class>
org.ysc.action.Testmain
</listener-class>
</listener></span>
具体实现代码:
<span style="font-size:18px;">package org.ysc.action
public class Testmain implements ServletContextListener{
private Timer timer = null;
//初始化监听器,创建实例,执行任务
public void contextInitialized(ServletContextEvent event){
timer = new Timer();
timer.schedule(new MyTimeTask(),0,1*1000);
}
//销毁监听器,停止执行任务
public void contextDestroyed(ServletContextEvent event){
//注意,在此计时器调用的计时器任务的 run 方法内调用此方法,就可以绝对确保正在执行的任务是此计时器所执行的最后一个任务。
timer.cancel();
}
}</span>
➷ Quartz 的具体实现
1. 程序直接启动,创建任务调度的方式
<span style="font-size:18px;">package org.yscTest.action
public class TestMain{
private static Scheduler sched;
public static void run() throws Exception{
//创建LzstoneTimeTask的定时任务
JobDetail jobDetail = new JobDetail("MyJob",sched.DEFAULT_GROUP,MyTimeTask.class);
//目标 创建任务计划,且定义执行时间为 每天中午的12点执行该定时任务
CronTrigger trigger = new CronTrigger("MyTrigger","myTrigger","0 0 12 * * ?");
sched = new org.quartz.impl.StdSchedulerFactory().getScheduler();
//将当前定义的job和触发器添加到任务调度器中进行管理
sched.scheduleJob(jobDetail,trigger);
//启动任务调度器
sched.start();
}
//停止任务调度
public static void stop() throws Exception{
sched.shutdown();
}
}
//执行
public class Main{
.............
public void run(){
TestMain.run();
}
............
}</span>
2.web的监听方式
<span style="font-size:18px;">package org.ysc.action
public class TestMainListener implements ServletContextListener{
private Timer timer = null;
//初始化监听器,创建实例,执行任务
public void contextInitialized(ServletContextEvent event){
TestMain.run();
}
//销毁监听器,停止执行任务
public void contextDestroyed(ServletContextEvent event){
TestMain.stop();
}
}</span>
web.xml的配置:
<span style="font-size:18px;"><listener>
<listener-class>
org.ysc.action.TestMainListener
</listener-class>
</listener></span>
3.Timer 和Quartz的对比:
Timer的定时器,原理简单,实现方便,上手容易;但是我们无法使用确切的时间(比如某天某点五十),并且我们要使用TImer必须继承指定的类,所以依赖性较强;
Quartz定时器,方便,在日期的设定上更加灵活方便,可以实现比较复杂的定时任务,但是我们需要实现指定的接口,必须引入指定的jar包;
两者的关系:
Quartz中有两种触发器,SimpleTrigger和CronTrigger,小编感觉:但从实现的方式和实现的效果来看,Timer和Quartz中的SimpleTrigger中是类似的,只是设定时长和间隔次数;
综上所述,两者各有各的优点,项目中的使用可以结合具体情况和定时的特点来选择这两种定时器;
➷ 扩展--spring的“”定时任务“
当提起spring时,我们第一反应都是它的IOC容器和aop日志,但是很少想起spring对定时任务的支持;下面小编就将spring中对Timer和Quartz的支持一一道来:
1.对Timer的支持
♚ 创建定时任务类:
<span style="font-size:18px;">package org.test.action
import java.util.TimeTask
public class MyTimeTask extends TimeTask{
public void run(){
//执行的定时器任务
}
}</span>
♚ 配置applicationContext.xml文件:
<span style="font-size:18px;"><!--注册定时执行任务实体-->
<bean id="lzstoneTimeTask" class="org.test.action.MyTimeTask3"/>
<!--注册定时器信息-->
<bean id="taskInfo" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<!--第一次执行任务前需要等待的时间,这里设置为3秒-->
<property name="delay">
<value>3000</value>
</property>
<!--设置任务的执行周期 这里设置为4秒-->
<property name="period">
<value>4000</value>
</property>
<!--设置具体执行的任务 这里设置为MyTimeTask3-->
<property name="timerTask">
<ref local="MyTimeTask3"/>
</property>
</bean>
<!--配置定时器任务的调度器-->
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<!--注册定时器列表-->
<property name="scheduledTimerTasks">
<list>
<ref local="taskInfo"/>
........
</list>
</property>
</bean></span>
♚ web项目中的启动设置
<span style="font-size:18px;"><context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener></span>
2. 对Quartz的支持
♚ 创建定时任务类:
<span style="font-size:18px;">package org.test.action
public class MyQuartzTask{
public void execute(){
//执行的定时器任务
}
}</span>
♚ 在applicationContext.xml中进行配置:
<span style="font-size:18px;"><!--注册定时执行任务实体-->
<bean id="MyQuartzTask" class="org.test.action.MyQuartzTask"/>
<!--注册定时器信息-->
<bean id="taskInfo" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!--指定要执行的定时任务类 这里是LzstoneQuartzTask-->
<property name="targetObject">
<ref local="MyQuartzTask"/>
</property>
<!--指定定时器任务类要执行的方法名称 这里是execute-->
<property name="targetMethod">
<value>execute</value>
</property>
</bean>
<!--配置定时器任务的调度器-->
<bean id="quartzTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<!--声明要运行的实体-->
<property name="jobDetail">
<ref local="taskInfo"/>
</property>
<!--设置运行时间-->
<property name="cronExpression">
<value>0 0 12 * * ?</value>
</property>
</bean>
<!--注册监听器-->
<bean id="registerQuartz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!--注册定时器实体 集合-->
<property name="triggers">
<list>
<ref local="quartzTrigger"/>
</list>
</property>
</bean></span>
如果我们需要使用Quartz框架来对既有程序中某个方法进行定期执行,可以使用以下的配置(以定时执行loadHomePageData方法为例):
首先,我们引入quartz的包和指定的版本;
然后在ApplicationContext.xml中进行如下配置:
第一步:启动触发器的配置开始-->设定每一个触发器对应的触发器
第二步:调度的配置开始,设定每一个触发器执行的频率(由于使用的CronTrigger所以这里我们使用的是克隆表达式)
第三步:给三个不同的任务指定要执行的方法
这样,一旦quartz启动,loadHomePageData的方法会以一个小时为间隔重复执行;PS:第二步和第三步省略了另外两个的配置;
以上就是小编对项目中定时任务应用的理解和总结,纯属个人理解,如有问题或者好的建议,请留言给小编哦!!