quartz学习二--监听、排除日期、线程

来源:互联网 发布:windows版icloud是什么 编辑:程序博客网 时间:2024/05/21 08:35
一、Listener
    1、基本概念
       (1)、分类
            JobListener

        TriggerListener

        SchedulerListener

       (2)、作用
            可以扩展框架并定制来做特定的事情。跟Spring,Hibernate,Servlet监听器类似.

       (3)、全局和非全局监听器
            a、JobListener 和 TriggerListener 可被注册为全局或非全局监听器。
        
            b、区别
           全局监听器能接收到所有的 Job/Trigger 的事件通知。
           全局监听器是主动意识的,它们为了执行它们的任务而热切的去寻找每一个可能的事件

           非全局监听器只能接收到那些在其上已注册了监听器的 Job 或 Triiger 的事件。
           非全局监听器一般是被动意识的,它们在所关注的 Trigger 激发之前或是 Job 执行之前什么事也不做。

    2、JobListener
       (1)、源码
            public interface JobListener {  
               //命名jobListener 只对非全局监听器有效  
               public String getName();  
      
               //Scheduler 在 JobDetail 将要被执行时调用这个方法。  
               public void jobToBeExecuted(JobExecutionContext context);  
      
               //Scheduler 在 JobDetail 即将被执行,但又被否决时调用这个方法。  
               public void jobExecutionVetoed(JobExecutionContext context);  
      
               //Scheduler 在 JobDetail 被执行之后调用这个方法。  
               public void jobWasExecuted(JobExecutionContext context,JobExecutionException jobException);  
            }

       (2)、使用
            JobListener jobListener = new SimpleJobListener("SimpleJobListener");         
            
            全局监听: scheduler.addGlobalJobListener(jobListener);
           
            局部监听: scheduler.addJobListener(jobListener);//依次完成,顺序不能颠倒
              jobDetail.addJobListener(jobListener.getName());
              scheduler.addjob(jobDetail,true);  

    3、TriggerListener
       (1)、源码
            public interface TriggerListener {  
               //命名triggerListener 只对非全局监听器有效  
               public String getName();  
 
               //当与监听器相关联的 Trigger 被触发,Job 上的 execute() 方法将要被执行时,调用这个方法。  
               //在全局TriggerListener 情况下,这个方法为所有 Trigger 被调用。(不要做耗时操作)  
               public void triggerFired(Trigger trigger, JobExecutionContext context);  
 
               //在 Trigger 触发后,Job 将要被执行时由调用这个方法。  
               //TriggerListener给了一个选择去否决 Job 的执行。假如这个方法返回 true,这个 Job 将不会为此次 Trigger 触发而得到执行。  
               public boolean vetoJobExecution(Trigger trigger, JobExecutidonContext context);  
 
               // Scheduler 调用这个方法是在 Trigger 错过触发时。  
               // JavaDoc 指出:你应该关注此方法中持续时间长的逻辑:在出现许多错过触发的 Trigger 时,长逻辑会导致骨牌效应。你应当保持这上方法尽量的小  
               public void triggerMisfired(Trigger trigger);  
 
               //Trigger 被触发并且完成了Job的执行时调用这个方法。  
               public void triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode);  
            }
            
       (2)、使用
            TriggerListener triggerListener = new SimpleTriggerListener();         
           
            全局监听: scheduler.addGlobalTriggerListener(triggerListener);
            
            局部监听: scheduler.addTriggerListener(triggerListener);
              trigger.addTriggerListener(triggerListener.getName());

    4、SchedulerListener
       (1)、源码
            public interface SchedulerListener {  
               //有新的JobDetail部署调用这个方法。  
               public void jobScheduled(Trigger trigger);  
      
               //卸载时调用这个方法。  
               public void jobUnscheduled(String triggerName, String triggerGroup);  
      
               //当一个Trigger到达再也不会触发时调用这个方法。  
               public void triggerFinalized(Trigger trigger);  
      
               //Scheduler 调用这个方法是发生在一个Trigger或多个Trigger被暂停时。假如是多个Trigger的话,triggerName 参数将为null。  
               public void triggersPaused(String triggerName, String triggerGroup);  
      
               //Scheduler 调用这个方法是发生成一个 Trigger 或 Trigger 组从暂停中恢复时。假如是多个Trigger的话,triggerName 参数将为 null。  
               public void triggersResumed(String triggerName,String triggerGroup);  
      
               //当一个或一组 JobDetail 暂停时调用这个方法。  
               public void jobsPaused(String jobName, String jobGroup);  
      
               //当一个或一组 Job 从暂停上恢复时调用这个方法。假如是多个Job,jobName参数将为 null。  
               public void jobsResumed(String jobName, String jobGroup);  
      
               // 在Scheduler 的正常运行期间产生一个严重错误时调用这个方法。错误的类型会各式的,但是下面列举了一些错误例子:  
               // 可以使用 SchedulerException 的 getErrorCode() 或者 getUnderlyingException() 方法或获取到特定错误的更详尽的信息  
               public void schedulerError(String msg, SchedulerException cause);  
      
               //Scheduler 调用这个方法用来通知 SchedulerListener Scheduler 将要被关闭。  
               public void schedulerShutdown();  
            }  
   
       (2)、使用
            scheduler.addSchedulerListener(schedulerListener);

二、org.quartz.Calendar
    1、定义
       专门用于屏闭一个时间区间,使 Trigger 在这个区间中不被触发。 是一些日历特定时间点的集合

    2、作用
       一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。

    3、原生Calendar实现
       org.quartz.impl.calendar.BaseCalender                 --->        为高级的 Calender 实现了基本的功能,实现了 org.quartz.Calender 接口
       org.quartz.impl.calendar.WeeklyCalendar                --->         排除星期中的一天或多天,例如,可用于排除周末
       org.quartz.impl.calendar.MonthlyCalendar                --->        排除月份中的数天,例如,可用于排除每月的最后一天
       org.quartz.impl.calendar.AnnualCalendar                --->        排除年中一天或多天
       org.quartz.impl.calendar.HolidayCalendar                --->        特别的用于从 Trigger 中排除节假日
       
    4、使用
       AnnualCalendar cal = new AnnualCalendar();
       ...
       scheduler.addCalendar("crmHolidays", cal, true, true);
       trigger.setCalendarName("crmHolidays");

三、ThreadPool
    1、作用
       使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率

    2、SimpleThreadPool
       一个Quartz默认实现的简单线程池,它足够健壮,能够应对大部分常用场景

    3、ThreadExecutor / DefaultThreadExecutor
       内部线程操作对象

    4、org.quartz.spi.ThreadPool 接口
       自定义 quartz 线程池

四、quartz与线程
    1、主处理线程(QuartzSchedulerThread)
       (1)、原理
            启动Scheduler时。QuartzScheduler被创建并创建一个org.quartz.core.QuartzSchedulerThread 类的实例。

            QuartzSchedulerThread 包含有决定何时下一个Job将被触发的处理循环。
        
        QuartzSchedulerThread 是一个 Java 线程。它作为一个非守护线程运行在正常优先级下。
    
       (2)、主处理轮循步骤
            a、当 Scheduler 正在运行时:
           检查是否有转换为 standby 模式的请求。

            b、假如 standby 方法被调用,等待继续的信号
           询问 JobStore 下次要被触发的 Trigger.

            c、如果没有 Trigger 待触发,等候一小段时间后再次检查

            d、假如有一个可用的 Trigger,等待触发它的确切时间的到来
           时间到了,为 Trigger 获取到 triggerFiredBundle.

           使用Scheduler和triggerFiredBundle 为 Job 创建一个JobRunShell实例

           在ThreadPool 申请一个线程运行 JobRunShell 实例.

    2、工作者线程
       (1)、原理
            Quartz 不会在主线程(QuartzSchedulerThread)中处理用户的Job。
        
        Quartz 把线程管理的职责委托给ThreadPool。

       (2)、org.quartz.simpl.SimpleThreadPool。
        SimpleThreadPool 创建了一定数量的 WorkerThread 实例来使得Job能够在线程中进行处理。

        WorkerThread 是定义在 SimpleThreadPool 类中的内部类,它实质上就是一个线程。

        要创建 WorkerThread 的数量以及配置他们的优先级是在文件quartz.properties中并传入工厂。

       (3)、流程
        主线程(QuartzSchedulerThread)请求ThreadPool去运行 JobRunShell 实例,
        ThreadPool 就检查看是否有一个可用的工作者线程。
        
        假如所以已配置的工作者线程都是忙的,ThreadPool 就等待直到有一个变为可用。

        当一个工作者线程是可用的, 并且有一个JobRunShell 等待执行,工作者线程就会调用 JobRunShell 类的 run() 方法。






0 0
原创粉丝点击