您的位置:首页 > 编程语言 > Java开发

java.util下的Timer,TimerTask和quartz的比较

2006-11-13 21:43 447 查看
Java中已经有一个timer类可以用来进行执行计划,定时任务。我们所要做的只是继承java.util.TimerTask类。如下所示:
packagecom.yourcompany.scheduling;
importjava.util.Calendar;
importjava.util.Date;
importjava.util.Timer;
importjava.util.TimerTask;
publicclassReportGeneratorextendsTimerTask{
publicvoidrun(){
System.out.println("Generatingreport");
//TODOgeneratereport
}
}
classMainApplication{
publicstaticvoidmain(String[]args){
TimertimernewTimer();
Calendardate=Calendar.getInstance();
date.set(
Calendar.DAY_OF_WEEK,
Calendar.SUNDAY
);
date.set(Calendar.HOUR,0);
date.set(Calendar.MINUTE,0);
date.set(Calendar.SECOND,0);
date.set(Calendar.MILLISECOND,0);
//ScheduletoruneverySundayinmidnight
timer.schedule(
newReportGenerator(),//TimerTask
date.getTime(),//Timer
1000*60*60*24*7//delay
);
}
}
这里有几个问题,我们的类继承了TimerTask,而timerTask也是实现了java.lang.Runnable接口。我们所要做的只是在我们自己的类里重置run()方法。所以我们的TimerTask类其实是一种线程,但线程的调度往往不是按照我们希望来实现的,因为一些垃圾收集等原因,我们计划的时间点,却没有执行必要的任务。这样会产生一些问题。虽然,Timer类也提供了
scheduleAtFixedRate()
方法用来在垃圾收集后能够快速的追上任务进度,但这个不一定是我们所需要的。特别是在一些J2EE服务器上Timer是无法控制的,因为它不在容器的权责范围内。另外的,这个任务调度也缺乏一些企业级所需要的特殊日期定制的功能,以及修改,查找任务的功能。这里我们要介绍的是一个开源项目:Quartz。Quartz定义了两种基本接口
Job
Trigger
。看名字也就知道,我们的任务必须实现Job,我们的时间触发器定义在Trigger内。看一个例子也许能更快的了解他的使用方法:
packagecom.yourcompany.scheduling;
importorg.quartz.*;
publicclassQuartzReportimplementsJob{
publicvoidexecute(JobExecutionContextcntxt)//
必须实现的方法
throwsJobExecutionException{
System.out.println(
"Generatingreport-"+
cntxt.getJobDetail().getJobDataMap().get("type")
);
//TODOGeneratereport
}
publicstaticvoidmain(String[]args){
try{
SchedulerFactoryschedFact
neworg.quartz.impl.StdSchedulerFactory();
Schedulersched=schedFact.getScheduler();
sched.start();
JobDetailjobDetail=
newJobDetail(
"IncomeReport",//
任务名
"ReportGeneration",//
任务组
QuartzReport.class//
任务执行的类
);
jobDetail.getJobDataMap().put(
"type",
"FULL"
)
;
CronTriggertriggernewCronTrigger(
"IncomeReport",//
触发器名
"ReportGeneration"//
触发器组
);
trigger.setCronExpression(//
触发器时间设定
"0012?*SUN"
);
sched.scheduleJob(jobDetail,trigger);//
执行任务
}catch(Exceptione){
e.printStackTrace();
}
}
}
这里面我们可以看到,当我们定义了任务执行
QuartzReport
类后,需要定一个
Scheduler
类用来执行计划任务。一个
JobDetail
类来描述这个任务的信息,包括任务信息,任务所在组,任务执行的类。然后还要定义一个触发器,类似的也包括触发器名,触发器所在组,触发器触发时间设定。最后是调度器
Scheduler
类执行计划任务。基本上一个计划任务执行的流程就完成了。当然,我们还看到了上面红色代表的内容,这些内容主要是提供在job方法执行的时候所需要的参数的提供。这里使用了
JobDataMap
类,它其实就是实现了map的特殊应用的一个类,使用方法与Map很相似。我们可以用put()输入参数。在Job类中使用
cntxt.getJobDetail().getJobDataMap().get("type")
方法获取输入的参数的值。这里的cntxt是
JobExecutionContext
。就是包含任务执行上下文的一个信息类。这样我们的一个基本的任务执行就可以搞定了。触发器有两类:
SimpleTrigger
and
CronTrigger
.。
SimpleTrigger
主要提供了跟java.util.Timer类相似的功能.。你可以在里面定义任务的起始时间,终止时间,任务的执行次数,任务执行的中间间隔。而
CronTrigger
类主要提供了更高级的任务调度时间设置,例如每个星期天的早上7点。
CronTrigger
的时间设置说明在最后来介绍。下面我们介绍一下在J2EE环境下如何来使用Quartz。首先,我们要配置web.xml,添加一下内容,主要是Quartz的初始化,<servlet><servlet-name>QuartzInitializer</servlet-name><display-name>QuartzInitializerServlet</display-name><servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class><load-on-startup>1</load-on-startup></servlet>然后还要有一个Quartz的配置文件quartz.properties放置在WEB-INF/classes目录下面。StdScheduleFactory()会读取它。配置如下
#
#ConfigureMainSchedulerProperties
#
org.quartz.scheduler.instanceName=TestScheduler
org.quartz.scheduler.instanceId=one
#
#ConfigureThreadPool
#
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=5
org.quartz.threadPool.threadPriority=4
#
#ConfigureJobStore
#
org.quartz.jobStore.misfireThreshold=5000
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
这里我们使用的
RAMJobStore
存储方式,这样如果我们的web服务器重启的话,我们所有未执行的任务信息都回丢失。当然,我们也有另外的选择,我们可以把这样的信息存储在数据库内,就是使用
JDBCJobStoreTX
#
#ConfigureThreadPool
#
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.tablePrefix=QRTZ_
#
#ConfigureDatasources
#
org.quartz.dataSource.myDS.driver=org.postgresql.Driver
org.quartz.dataSource.myDS.URL=jdbc:postgresql:dev
org.quartz.dataSource.myDS.user=dejanb
org.quartz.dataSource.myDS.password=
org.quartz.dataSource.myDS.maxConnections5
附:cronExpression配置说明
字段允许值允许的特殊字符
0-59,-*/
0-59,-*/
小时0-23,-*/
日期1-31,-*?/LWC
月份1-12或者JAN-DEC,-*/
星期1-7或者SUN-SAT,-*?/LC#
年(可选)留空,1970-2099,-*/
Cron的小小说明
表示方式意义
"0012**?"Fireat12pm(noon)everyday
"01510?**"Fireat10:15ameveryday
"01510**?"Fireat10:15ameveryday
"01510**?*"Fireat10:15ameveryday
"01510**?2005"Fireat10:15ameverydayduringtheyear2005
"0*14**?"Fireeveryminutestartingat2pmandendingat2:59pm,everyday
"00/514**?"Fireevery5minutesstartingat2pmandendingat2:55pm,everyday
"00/514,18**?"Fireevery5minutesstartingat2pmandendingat2:55pm,ANDfireevery5minutesstartingat6pmandendingat6:55pm,everyday
"00-514**?"Fireeveryminutestartingat2pmandendingat2:05pm,everyday
"010,4414?3WED"Fireat2:10pmandat2:44pmeveryWednesdayinthemonthofMarch.
"01510?*MON-FRI"Fireat10:15ameveryMonday,Tuesday,Wednesday,ThursdayandFriday
"0151015*?"Fireat10:15amonthe15thdayofeverymonth
"01510L*?"Fireat10:15amonthelastdayofeverymonth
"01510?*6L"Fireat10:15amonthelastFridayofeverymonth
"01510?*6L"Fireat10:15amonthelastFridayofeverymonth
"01510?*6L2002-2005"Fireat10:15amoneverylastfridayofeverymonthduringtheyears2002,2003,2004and2005
"01510?*6#3"Fireat10:15amonthethirdFridayofeverymonth
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: