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

Java 中已经有一个 timer 类可以用来进行执行计划,定时任务。我们所要做的只是 继承 java.util.TimerTask 类。如下所示:
package com.yourcompany.scheduling;
 

 

import java.util.Calendar;
 
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

 

public class ReportGenerator extends TimerTask {
 

 

 public void run() {
 
    System.out.println("Generating report");
    //TODO generate report
 }

 

}
 

 

class MainApplication {
 

 

 public static void main(String[] args) {
    Timer timer new Timer();
    Calendar date = 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);
    // Schedule to run every Sunday in midnight
    timer.schedule(
      new ReportGenerator(),   // TimerTask
      date.getTime(),          // Timer
      1000 * 60 * 60 * 24 * 7   // delay
    );
 }
}

 这里有几个问题,我们的类继承了TimerTask ,而timerTask 也是实现了 java.lang.Runnable 接口。我们所要做的只是在我们自己的类里重置 run() 方法。所以我们的TimerTask类其实是一种线程,但线程的调度往往不是按照我们希望来实现的,因为一些垃圾收集等原因,我们计划的时间点,却没有执行必要的任务。这样会产生一些问题。虽然,Timer 类也提供了scheduleAtFixedRate() 方法用来在垃圾收集后能够快速的追上任务进度,但这个不一定是我们所需要的。特别是在 一些 J2EE 服务器上 Timer 是无法控制的,因为它不在容器的权责范围内。另外的,这个任务调度也缺乏一些企业级所需要的 特殊 日期定制的功能,以及修改,查找任务的功能。

       这里我们要介绍的是一个开源项目:Quartz

       Quartz 定义了两种 基本接口 JobTrigger 。 看名字也就知道,我们的任务必须实现 Job, 我们的时间触发器定义在 Trigger 内。 看一个例子也许能更快的了解他的使用方法: package com.yourcompany.scheduling;

 

 

import org.quartz.*;
 

 

public class QuartzReport implements Job {
 

 

 public void execute(JobExecutionContext cntxt) //必须实现的方法
 
    throws JobExecutionException {
      System.out.println(
        "Generating report - " +
cntxt.getJobDetail().getJobDataMap().get("type")
      );
      //TODO Generate report
 }

 

 public static void main(String[] args) {
 
    try {
      SchedulerFactory schedFact 
       new org.quartz.impl.StdSchedulerFactory();
      Scheduler sched = schedFact.getScheduler();
      sched.start();
      JobDetail jobDetail =
        new JobDetail(
          "Income Report",       // 任务名
          "Report Generation", // 任务组
          QuartzReport.class    //任务执行的类
        );
      jobDetail.getJobDataMap().put(
                                "type",   
                                "FULL"
                               );

 

      CronTrigger trigger new CronTrigger(
 
        "Income Report",              //触发器名
        "Report Generation"          //触发器组
      );
      trigger.setCronExpression(     // 触发器时间设定
        "0 0 12 ? * SUN"
      );

 

      sched.scheduleJob(jobDetail, trigger); // 执行任务
 

 

    } catch (Exception e) {
      e.printStackTrace();
    }
 }
}
这里面我们可以看到,当我们定义了任务执行 QuartzReport 类后,需要定一个Scheduler类用来执行计划任务。
一个JobDetail 类来描述这个任务的信息,包括任务信息,任务所在组,任务执行的类。
然后还要定义一个 触发器,类似的也包括触发器名,触发器所在组,触发器触发时间设定。
最后是调度器Scheduler类执行计划任务。基本上一个计划任务执行的流程就完成了。
当然,我们还看到了上面红色代表的内容,这些内容主要是提供在job方法执行的时候所需要的参数的提供。这里使用了JobDataMap 类,它其实就是实现了map的特殊应用的一个类,使用方法与Map 很相似。我们可以用 put() 输入参数。在Job类中使用cntxt.getJobDetail().getJobDataMap().get("type") 方法获取输入的参数的值。这里的cntxtJobExecutionContext 。就是包含任务执行上下文的一个信息类。这样我们的一个基本的任务执行就可以搞定了。

触发器有两类:SimpleTrigger andCronTrigger. 。SimpleTrigger主要提供了跟 java.util.Timer 类相似的功能.。你可以在里面定义 任务的起始时间,终止时间,任务的执行次数,任务执行的中间间隔 。 而 CronTrigger类主要提供了更高级的任务调度时间设置,例如 每个星期天的早上7点  。 CronTrigger的时间设置说明在最后来介绍。

下面我们介绍一下在 J2EE 环境下如何来使用 Quartz 。

首先,我们要配置 web.xml ,添加 一下内容,主要是Quartz 的初始化,

<servlet>

          <servlet-name>QuartzInitializer</servlet-name>

          <display-name>Quartz Initializer Servlet</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()会读取它。配置如下 #

 
# Configure Main Scheduler Properties 
#

 

org.quartz.scheduler.instanceName = TestScheduler
 
org.quartz.scheduler.instanceId = one

 

#
 
# Configure ThreadPool 
#

 

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
 
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 4

 

#
 
# Configure JobStore 
#

 

org.quartz.jobStore.misfireThreshold = 5000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

这里我们使用的 RAMJobStore 存储方式,这样如果我们的web服务器重启的话,我们所有未执行的任务信息都回丢失。当然,我们也有另外的选择,我们可以把这样的信息存储在数据库内,就是使用 JDBCJobStoreTX

#
# Configure ThreadPool 
#

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_

 

#
 
# Configure Datasources 
#

 

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.maxConnections 5

附:cronExpression配置说明

字段

 

允许值

 

允许的特殊字符

 

0-59

 

, - * /

 

0-59

 

, - * /

小时

 

0-23

 

, - * /

日期

 

1-31

 

, - * ? / L W C

月份

 

1-12 或者 JAN-DEC

 

, - * /

星期

 

1-7 或者 SUN-SAT

 

, - * ? / L C #

年(可选)

 

留空, 1970-2099

 

, - * /

Cron 的小小说明

表示方式

意义

"0 0 12 * * ?"

Fire at 12pm (noon) every day

"0 15 10 ? * *"

Fire at 10:15am every day

"0 15 10 * * ?"

Fire at 10:15am every day

"0 15 10 * * ? *"

Fire at 10:15am every day

"0 15 10 * * ? 2005"

Fire at 10:15am every day during the year 2005

"0 * 14 * * ?"

Fire every minute starting at 2pm and ending at 2:59pm, every day

"0 0/5 14 * * ?"

Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day

"0 0/5 14,18 * * ?"

Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day

"0 0-5 14 * * ?"

Fire every minute starting at 2pm and ending at 2:05pm, every day

"0 10,44 14 ? 3 WED"

Fire at 2:10pm and at 2:44pm every Wednesday in the month of March.

"0 15 10 ? * MON-FRI"

Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday

"0 15 10 15 * ?"

Fire at 10:15am on the 15th day of every month

"0 15 10 L * ?"

Fire at 10:15am on the last day of every month

"0 15 10 ? * 6L"

Fire at 10:15am on the last Friday of every month

"0 15 10 ? * 6L"

Fire at 10:15am on the last Friday of every month

"0 15 10 ? * 6L 2002-2005"

Fire at 10:15am on every last friday of every month during the years 2002, 2003, 2004 and 2005

"0 15 10 ? * 6#3"

Fire at 10:15am on the third Friday of every month

 

 

 

 

 

 

 

 

 

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值