Quartz 任务调度机制笔记——01

实例:
1、代码实现Demo
@Test
     public  void  demo01()  throws  InterruptedException{
        //获取调度器
       SchedulerFactory schedulerFactory =  new  StdSchedulerFactory();
       Scheduler scheduler =  null ;
        try  {
           scheduler = StdSchedulerFactory.getDefaultScheduler();
          
            //引进作业程序这,里的HelloJob是一个Job的继承类,重载的excute方法
           JobDetail jobDetail = JobBuilder.newJob(HelloJob. class )
                                           .withIdentity( "helloJob" ,  "group01"  )
                                           .build();
            //生成一个触发器,这里这个SimpleTriggerImpl可以被其他的Trigger替换掉的
           SimpleTriggerImpl simpleTriggerImpl =  new  SimpleTriggerImpl(  "trigger" ,  "group01"  );
           //我使用的是:
            //Trigger simpleTriggerImpl = TriggerBuilder.newTrigger().withIdentity("trigger", "group01").build();
           simpleTriggerImpl.setStartTime(  new  Date(System.currentTimeMillis()));
          
           simpleTriggerImpl.setRepeatInterval(2000);
           simpleTriggerImpl.setRepeatCount(10);
          
            //作业和触发器设置到调度器中
           scheduler.scheduleJob(jobDetail, simpleTriggerImpl);
            //启动调度器
           System.  out .println(jobDetail.getKey().toString());
           scheduler.start();
   //注意,在Quartz中,这个调度器的生命周期是和主线程相关的,所有如果主线程退出了,那么调度器也就结束了
           Thread. sleep(20000);
        }  catch  (SchedulerException e) {
             //  TODO  Auto-generated catch block
            e.printStackTrace();
        } finally {
            System.  out .println(HelloJob.  count );
        }
    }

2、配置文件实现:Demo
quartz.properties

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

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

org.quartz.plugin.jobInitializer.class =  org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames =  jobs.xml #自己的job配置文件
org.quartz.plugin.jobInitializer.failOnFileNotFound =  true
org.quartz.plugin.jobInitializer.scanInterval =  10
org.quartz.plugin.jobInitializer.wrapInUserTransaction =  false

jobs.xml

<? xml  version = '1.0'  encoding =  'utf-8' ?>
< job-scheduling-data  xmlns =  "http://www.quartz-scheduler.org/xml/JobSchedulingData"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.quartz-scheduler.org/xml/JobSchedulingData
                          http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"  version =  "1.8" >
   <  schedule >
   <  job >          
     < name  > hello  </ name  >
     < group  > MYJOB_GROUP  </ group  >
     < description  > The job description  </ description  >
     < job-class  > com.qunar.xueping.HelloJob  </ job-class  > ##这是为自己的job实现类
     < job-data-map  > #设置JobDataMap key-value
       < entry  >
           < key  > key  </ key  >
           < value  > hotdog </ value >
        </ entry  >
        < entry  >
            < key  > key2  </ key  >
            < value  > ketchup, mayo </  value >
        </ entry  >
      </ job-data-map  >   
    </ job  >
     
     < trigger  >      
      < simple  >      
        < name  > scanTrigger  </ name  >      
        < group  > DEFAULT  </ group  >      
        < job-name  > hello  </ job-name  >      
        < job-group  > MYJOB_GROUP  </ job-group  >            
        < repeat-count  > 3  </ repeat-count  >      
        < repeat-interval  > 1000  </ repeat-interval  >      
      </ simple  >      
     </ trigger  >         
   </  schedule >
</ job-scheduling-data >
注:具体的Schedule调度: 
scheduler = StdSchedulerFactory. getDefaultScheduler (); 
schedule.start();

进阶:

1、在调度器中表示一个job或者一个trigger的方式是通过一个JobKey来表示的,
JobKey jobKey = new JobKey("name" , "group");
Scheduler可以对job和Trigger进行一些操作

2、在进行任务调度过程中,可以通过JobDataMap来put Info到Job中去

3、通过SchedulerMetaData metaData = schedule.getMetaData(),里面有一些schedule的常见设置,例如threadPool的size,另外值得注意的是,metaData.getNumberOfJobsException()方法,这个方法返回的是当先执行了多少个job
(疑问:为什么我的Trigger的withRepeatCount设置的是10,但最终job的excute方法执行了11次)

4、注意Job的两个注释:@PersistJobDataAfterExecution @DisallowConcurrentExecution 做什么用,顾名思义啦

5、关于故障的恢复:
     在Quartz中对于故障的解决办法是将job persist到数据中,然后通过状态标识Recovering需要恢复的Job
          参考网站: http://ygydaiaq-gmail-com.iteye.com/blog/1729626
                                 http://www.24xuexi.com/w/2011-04-16/88179.html

6、Listener:quartz有自己的监听器JobListener,TriggerListstener,SchedulerListerner
举例:JobListener:

public  class  MyJobListener  implements  JobListener{

     public  String getName() {
         //  TODO  Auto-generated method stub
         return  "MyJobListener" ;
    }
     public  void  jobToBeExecuted(JobExecutionContext context) {
         //  TODO  Auto-generated method stub
        System. out .println(context.getJobDetail().getJobDataMap().getString( "key" )+ "jobToBeExecuted----" );
    }

     public  void  jobExecutionVetoed(JobExecutionContext context) {
         //  TODO  Auto-generated method stub
        System. out .println(context.getJobDetail().getJobDataMap().getString( "key" )+ "jobExecutionVetoed----" );
    }

     public  void  jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
         //  TODO  Auto-generated method stub
        System. out .println(context.getJobDetail().getJobDataMap().getString( "key" )+ "jobWasExecuted----" );
    }

}

设置Listener:
  @Test
     public  void  testJob03(){
        Scheduler scheduler  =  null ;
         try  {
            scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.getListenerManager()
     .addJobListener( new  MyJobListener() , KeyMatcher.keyEquals(  new  JobKey( "hello"  ,  "MYJOB_GROUP" )));
            scheduler.start();
            Thread. sleep(20000);
        }  catch  (Exception e) {
             //  TODO : handle exception
            e.printStackTrace();
        }
    }

7、Quartz的故障恢复机制
默认情况下,Quartz中所提交的任务都是独立的运行在线程中,这意味着机器出现故障或任何原因导致这个线程被干掉了,那么提交的任务就无法继续也无法恢复
解决方法:在出现故障时将任务进行的状态保存下来,Quartz内置了数据库持久化的模块
配置文件:quartz.xml
#配置RAMJobStore
org.quartz.jobStore.class =  org.quartz.simpl.RAMJobStore

#数据库配置
org.quartz.jobStore.misfireThreshold= 60000
org.quartz.jobStore.class= org.quartz.simpl.RAMJobStore

org.quartz.dataSource.DATA_SOURCE_NAME.driver= com.mysql.jdbc.Driver
org.quartz.dataSource.DATA_SOURCE_NAME.URL= jdbc:mysql://localhost:3306/ dbname
org.quartz.dataSource.DATA_SOURCE_NAME.user= root
org.quartz.dataSource.DATA_SOURCE_NAME.password=  12345
org.quartz.jobStore.class= org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass= org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource= DATA_SOURCE_NAME

创建数据库:
导入quartz文档中的mysql.sql创建好需要的数据表

故障恢复Demo:
   @Test
   //@Ignore
     public  void  recovery() {
        Scheduler scheduler  =  null ;
         try  {
            scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.getListenerManager()
     .addJobListener( new  MyJobListener() , KeyMatcher.keyEquals(  new  JobKey( "hello"  ,  "MYJOB_GROUP" )));
            scheduler.start();
         //调用schedule的shutdown()方法,这个时候job还没有执行完成,所有会被记录到数据表qrtz_triggers中
            scheduler.shutdown();
        }  catch  (Exception e) {
             //  TODO : handle exception
            e.printStackTrace();
        }

         try  {
             //重新获取schedule调度器,值得注意的是这里获取的调度器同上面的调度器不是同一个对象,而是一个新的调度器
            scheduler = StdSchedulerFactory.getDefaultScheduler(); 
            scheduler.start();
         //得到group为TestDB的数据中的记录
            Set<TriggerKey> triggers = scheduler.getTriggerKeys(GroupMatcher.groupEquals ( "TestDB"  ));
            Iterator< TriggerKey> iterator = triggers.iterator();
             for  (TriggerKey triggerKey : triggers) {
                Trigger trigger = scheduler.getTrigger(triggerKey);
//继续执行没执行完的trigger
                scheduler.rescheduleJob(triggerKey, trigger);
            }
            Thread. sleep(40000);
        }  catch  (SchedulerException e) {
            e.printStackTrace();
        }  catch  (InterruptedException e) {
             //  TODO  Auto-generated catch block
            e.printStackTrace();
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值