Java任务调度框架Quartz及模拟实现

1. 普通定时器

利用Timer定时器,来完成简单的定时任务

//延迟5秒启动,每隔两秒执行一次
public static void main(String[] args)
   {
      Timer timer = new Timer();
      timer.schedule(new TimerTask() {         
         @Override
         public void run() {
           System.out.println("my task is running");
            }
           }, 5000,2000); 
     }
2. 多任务的调度(模拟Quartz调度框架)

先创建一个Job的接口,实现一个excute的任务执行的方法

  public interface Job
  {    
    public void excute();
   }

创建一个Trigger接口,实现一个Boolean类型的方法,根据返回值true或false来调度任务执行

public interface Trigger
{
    public boolean Run(long curTime)
}

实现一个QueryJob,模拟数据的查询

public class QueryJob implements Job
{    
 SimpleDateFormat format = new      SimpleDateFormat("yyyy-MM-dd HH:mm:ss");         @Override    
     public void excute()  
     {        System.out.println(format.format(new          Date())+"数据查询中");  
     }
  }

实现一个每隔N秒执行一次的调度计划

public class ClockTrigger implements Trigger
{
     private long startTime; //执行开始时间
     private long period; //执行周期
     private long preTime = 0;//上一次执行时间
  
     @Override
     public boolean canRun(long curTime)
     {
           if(curTime >= startTime)
           {
                //第一次执行
                if(preTime == 0)
                {
                   preTime = curTime;
                   return true;
                }
                //后续执行
                else if(preTime + period <= curTime)
                {
                     preTime = curTime;
                     return true;
                }
           }
           return false;
     }
     public long getStartTime() {

          return startTime;
     }
     public void setStartTime(long startTime) {

           this.startTime = startTime;
     }
     public long getPeriod() {

           return period;
     }
     public void setPeriod(long period) {

           this.period = period;
     }
}

创建一个调度任务服务,向调度计划Trigge类中传入当前时间,通过Trigger类返回的boolean值来判断当前任务是否执行

public class TimerService 
{
     private Map<Job,Trigger> jobs;
     public TimerService()
     {
         this.jobs = new HashMap<Job,Trigger>();
     }
     public void addJob(Job job,Trigger trigger)
     {
           this.jobs.put(job, trigger);
     }

     //检查当前的job是否到执行时间
     public void schedule()
     {
           new Timer().schedule(new TimerTask()
           {
               @Override
               public void run() {
               long curTime = new Date().getTime();
              for(Entry<Job, Trigger>myJob : 
jobs.entrySet())
                    {
                         Trigger trigger = myJob.getValue();
                  if(trigger.canRun(curTime))
                    {
                      Job job = myJob.getKey();
                      new Thread(new Runnable()                            {                                    
                                     @Override
                                     public void run()                            {                                       
                                         job.execute();
                                     }
                                }).start();
                           }
                     }
                }
           }, 0,1000);

将任务的执行加入新的线程是为了防止发生阻塞

public static void main(String[] args){       
  TimerService time = new TimerService();   
  Job job = new QueryJob();    
//设置为当前时间加五秒后执行    
 Calendar calendar =Calendar.getInstance();     
 calendar.add(calendar.SECOND,5);     
 QueryTrigger queryTrigger = new  QueryTrigger();    
//每隔两秒执行一次    
 queryTrigger.setPeriod(2000);   
 queryTrigger.setStartTime(calendar.getTimeInMillis());    
 time.addJob(job,queryTrigger);     
 time.schedule();}
Quartz任务调度框架
  • 需要导入Quartz的Jar包
    在这里插入图片描述

先创建一个任务类Job,实现Quartz提供的接口

public class PrintJob implements Job
{
     private SimpleDateFormat format = new 
SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     @Override
     public void execute(JobExecutionContext context) throws JobExecutionException
     {    
           System.out.println(format.format(new Date())+"我打印了");
     }   
}

SimpleTrigger:一般用于实现每隔一定时间执行任务,以及重复多少次如每 2 小时执行一次,重复执行 5 次。SimpleTrigger 内部实现机制是通过计算间隔时间来计算下次的执行时间,这就导致其不适合调度定时的任务。例如我们想每天的 1:00AM 执行任务,如果使用 SimpleTrigger 的话间隔时间就是一天。注意这里就会有一个问题,即当有 misfired 的任务并且恢复执行时,该执行时间是随机的(取决于何时执行 misfired 的任务,例如某天的 3:00PM)。这会导致之后每天的执行时间都会变成 3:00PM,而不是我们原来期望的 1:00AM。

public class SimpleTriggerDemo
{
     public static void main(String[] args) throws 
SchedulerException
     {
         Scheduler scheduler = 
StdSchedulerFactory.getDefaultScheduler();
           //创建JobDetail实例,并与PprintJob类绑定,通过反射调用Job中的执行方法
           JobDetail job = new JobDetail("print","myGroup",PrintJob.class);
           Trigger trigger = new 
SimpleTrigger("printTrigger",3,2000);
           scheduler.scheduleJob(job,trigger);
           scheduler.start();
     }
}

CronTirgger:利用一个包含 7 个字段的表达式来表示时间调度方式。例如,“0 15 10 * * ? *” 表示每天的 10:15AM 执行任务。对于涉及到星期和月份的调度,CronTirgger 是最适合的,甚至某些情况下是唯一选择。例如,“0 10 14 ? 3 WED” 表示三月份的每个星期三的下午 14:10PM 执行任务。读者可以在具体用到该 trigger 时再详细了解每个字段的含义

public class ConTriggerDemo
{
     public static void main(String[] args)
     { 
           Scheduler scheduler = null;
           try {
                scheduler = 
StdSchedulerFactory.getDefaultScheduler();
           } catch (SchedulerException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
           }
           //创建JobDetail实例,并与PprintJob类绑定,通过反射调用Job中的执行方法
           JobDetail job = new 
JobDetail("print","myGroup",PrintJob.class);
           Trigger trigger =null;
            try {
                trigger = new CronTrigger("print","myGroup","0/5 
* * * * ?");
           } catch (ParseException e1) {
                // TODO 自动生成的 catch 块
                e1.printStackTrace();
           }
           try { 
                scheduler.scheduleJob(job,trigger);
           } catch (SchedulerException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
           }
           try {
                scheduler.start();
           } catch (SchedulerException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
           }
     }
}

CronTirgger表达式规则
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值