`

Quartz源码分析

阅读更多
Quartz是运用最广的任务调度框架,它最核心的组成部分是Scheduler、Trigger、JobDetail,然后给Scheduler配置个线程QuartzSchedulerThread,此线程在Scheduler初始化时启动,等待Scheduler start,然后从JobStore里拿到最近要触发的Trigger,以线程等待的方式等到trigger触发时间点,之后就是执行trigger所关联的JobDetail,最后清扫战场。Scheduler初始化、start和trigger执行的时序图如下所示:





其中,最核心的地方是QuartzSchedulerThread运行机制。下面解析一下它的run方法:

view plaincopy to clipboardprint?
public void run() {  
        boolean lastAcquireFailed = false;  
          
        while (!halted) {  
            try {  
                // check if we're supposed to pause...  
                synchronized (pauseLock) {  
                    while (paused && !halted) {  
                        try {  
                            // wait until togglePause(false) is called...  
                            pauseLock.wait(100L);  
                        } catch (InterruptedException ignore) {  
                        }  
                    }  
      
                    if (halted) {  
                        break;  
                    }  
                }  
           ......  
      }  

public void run() {
        boolean lastAcquireFailed = false;
       
        while (!halted) {
            try {
                // check if we're supposed to pause...
                synchronized (pauseLock) {
                    while (paused && !halted) {
                        try {
                            // wait until togglePause(false) is called...
                            pauseLock.wait(100L);
                        } catch (InterruptedException ignore) {
                        }
                    }
   
                    if (halted) {
                        break;
                    }
                }
           ......
      }
}

以上是run的最开头的一段,不难看出这是在等待scheduler的start,实际上Quartz就是通过线程的wait或sleep来实现时间调度。继续看代码:

view plaincopy to clipboardprint?
Trigger trigger = null;  
long now = System.currentTimeMillis();  
signaled = false;  
try {  
    trigger = qsRsrcs.getJobStore().acquireNextTrigger(  
            ctxt, now + idleWaitTime);  
    lastAcquireFailed = false;  
} catch (JobPersistenceException jpe) {  
    if(!lastAcquireFailed) {  
        qs.notifySchedulerListenersError(  
            "An error occured while scanning for the next trigger to fire.",  
            jpe);  
    }  
    lastAcquireFailed = true;  
} catch (RuntimeException e) {  
    if(!lastAcquireFailed) {  
        getLog().error("quartzSchedulerThreadLoop: RuntimeException " 
                +e.getMessage(), e);  
    }  
    lastAcquireFailed = true;  

Trigger trigger = null;
long now = System.currentTimeMillis();
signaled = false;
try {
    trigger = qsRsrcs.getJobStore().acquireNextTrigger(
            ctxt, now + idleWaitTime);
    lastAcquireFailed = false;
} catch (JobPersistenceException jpe) {
    if(!lastAcquireFailed) {
        qs.notifySchedulerListenersError(
            "An error occured while scanning for the next trigger to fire.",
            jpe);
    }
    lastAcquireFailed = true;
} catch (RuntimeException e) {
    if(!lastAcquireFailed) {
        getLog().error("quartzSchedulerThreadLoop: RuntimeException "
                +e.getMessage(), e);
    }
    lastAcquireFailed = true;
}

这段代码是从jobStore里拿到下一个要执行的trigger,一般情况下jobStore使用的是RAMJobStore,即trigger等相关信息存放在内存里,如果需要把任务持久化就得使用可持久化JobStore。继续看代码:

view plaincopy to clipboardprint?
now = System.currentTimeMillis();  
long triggerTime = trigger.getNextFireTime().getTime();  
long timeUntilTrigger = triggerTime - now;  
long spinInterval = 10;  
int numPauses = (int) (timeUntilTrigger / spinInterval);  
while (numPauses >= 0 && !signaled) {  
    try {  
        Thread.sleep(spinInterval);  
    } catch (InterruptedException ignore) {  
    }  
    now = System.currentTimeMillis();  
    timeUntilTrigger = triggerTime - now;  
    numPauses = (int) (timeUntilTrigger / spinInterval);  
}  
if (signaled) {  
    try {  
        qsRsrcs.getJobStore().releaseAcquiredTrigger(  
                ctxt, trigger);  
    } catch (JobPersistenceException jpe) {  
        qs.notifySchedulerListenersError(  
                "An error occured while releasing trigger '" 
                        + trigger.getFullName() + "'",  
                jpe);  
        // db connection must have failed... keep  
        // retrying until it's up...  
        releaseTriggerRetryLoop(trigger);  
    } catch (RuntimeException e) {  
        getLog().error(  
            "releaseTriggerRetryLoop: RuntimeException " 
            +e.getMessage(), e);  
        // db connection must have failed... keep  
        // retrying until it's up...  
        releaseTriggerRetryLoop(trigger);  
    }  
    signaled = false;  
    continue;  

now = System.currentTimeMillis();
long triggerTime = trigger.getNextFireTime().getTime();
long timeUntilTrigger = triggerTime - now;
long spinInterval = 10;
int numPauses = (int) (timeUntilTrigger / spinInterval);
while (numPauses >= 0 && !signaled) {
    try {
        Thread.sleep(spinInterval);
    } catch (InterruptedException ignore) {
    }
    now = System.currentTimeMillis();
    timeUntilTrigger = triggerTime - now;
    numPauses = (int) (timeUntilTrigger / spinInterval);
}
if (signaled) {
    try {
        qsRsrcs.getJobStore().releaseAcquiredTrigger(
                ctxt, trigger);
    } catch (JobPersistenceException jpe) {
        qs.notifySchedulerListenersError(
                "An error occured while releasing trigger '"
                        + trigger.getFullName() + "'",
                jpe);
        // db connection must have failed... keep
        // retrying until it's up...
        releaseTriggerRetryLoop(trigger);
    } catch (RuntimeException e) {
        getLog().error(
            "releaseTriggerRetryLoop: RuntimeException "
            +e.getMessage(), e);
        // db connection must have failed... keep
        // retrying until it's up...
        releaseTriggerRetryLoop(trigger);
    }
    signaled = false;
    continue;
}

此段代码是计算下一个trigger的执行时间和现在系统时间的差,然后通过循环线程sleep的方式暂停住此线程,一直等到trigger的执行时间点。继续看代码:

view plaincopy to clipboardprint?
import org.quartz.core.JobRunShell;  
JobRunShell shell = null;  
try {  
    shell = qsRsrcs.getJobRunShellFactory().borrowJobRunShell();  
    shell.initialize(qs, bndle);  
} catch (SchedulerException se) {  
    try {  
        qsRsrcs.getJobStore().triggeredJobComplete(ctxt,  
                trigger, bndle.getJobDetail(), Trigger.INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR);  
    } catch (SchedulerException se2) {  
        qs.notifySchedulerListenersError(  
                "An error occured while placing job's triggers in error state '" 
                        + trigger.getFullName() + "'", se2);  
        // db connection must have failed... keep retrying  
        // until it's up...  
        errorTriggerRetryLoop(bndle);  
    }  
    continue;  
}  
if (qsRsrcs.getThreadPool().runInThread(shell) == false) {  
    try {  
        getLog().error("ThreadPool.runInThread() return false!");  
        qsRsrcs.getJobStore().triggeredJobComplete(ctxt,  
                trigger, bndle.getJobDetail(), Trigger.INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR);  
    } catch (SchedulerException se2) {  
        qs.notifySchedulerListenersError(  
                "An error occured while placing job's triggers in error state '" 
                        + trigger.getFullName() + "'", se2);  
        // db connection must have failed... keep retrying  
        // until it's up...  
        releaseTriggerRetryLoop(trigger);  
    }  

import org.quartz.core.JobRunShell;
JobRunShell shell = null;
try {
    shell = qsRsrcs.getJobRunShellFactory().borrowJobRunShell();
    shell.initialize(qs, bndle);
} catch (SchedulerException se) {
    try {
        qsRsrcs.getJobStore().triggeredJobComplete(ctxt,
                trigger, bndle.getJobDetail(), Trigger.INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR);
    } catch (SchedulerException se2) {
        qs.notifySchedulerListenersError(
                "An error occured while placing job's triggers in error state '"
                        + trigger.getFullName() + "'", se2);
        // db connection must have failed... keep retrying
        // until it's up...
        errorTriggerRetryLoop(bndle);
    }
    continue;
}
if (qsRsrcs.getThreadPool().runInThread(shell) == false) {
    try {
        getLog().error("ThreadPool.runInThread() return false!");
        qsRsrcs.getJobStore().triggeredJobComplete(ctxt,
                trigger, bndle.getJobDetail(), Trigger.INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR);
    } catch (SchedulerException se2) {
        qs.notifySchedulerListenersError(
                "An error occured while placing job's triggers in error state '"
                        + trigger.getFullName() + "'", se2);
        // db connection must have failed... keep retrying
        // until it's up...
        releaseTriggerRetryLoop(trigger);
    }
}

此段代码就是包装trigger,然后通过以JobRunShell为载体,在threadpool里执行trigger所关联的jobDetail。

之后的代码就是清扫战场,就不在累述。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cutesource/archive/2009/12/08/4965520.aspx
  • 大小: 44.8 KB
分享到:
评论

相关推荐

    quartz集群调度机制调研及源码分析

    Quartz是一个开源的作业调度框架,它是用Java编写的,可以用于开发在特定时间点或周期性执行任务的应用程序。...理解Quartz集群调度机制及其源码分析,对于开发稳定、可靠的分布式任务调度系统至关重要。

    quartz源码解析(一)

    这篇博客“quartz源码解析(一)”可能是博主对Quartz核心原理、设计模式以及其实现细节的一个初步探讨。 Quartz的源码分析可以从以下几个方面入手: 1. **设计模式**: - **工厂模式**:Quartz中Job和Trigger的...

    Quartz.NET 官方源码及演示例子

    **源码分析** 1. **Quartz.build**:可能是构建脚本,用于构建整个项目,可能包含编译、测试和打包步骤。 2. **Quartz.2010.sln** 和 **Quartz.Server.2010.sln**:这是Visual Studio解决方案文件,用于打开和管理...

    quartz1.6.0源码

    源码分析有助于深入理解其内部工作原理,从而更好地利用它来满足各种复杂的定时需求。Quartz 1.6.0源码包提供了一个宝贵的资源,帮助开发者探索其设计模式、线程管理以及任务调度的机制。 1. **Quartz核心概念** -...

    quartz 时间调度器的使用

    Quartz 源码分析 了解 Quartz 的内部工作机制可以帮助你更好地利用这个库。Quartz 的源码提供了丰富的注释,你可以查看 `org.quartz.impl.StdSchedulerFactory`、`org.quartz.Scheduler`、`org.quartz.Trigger` 和 ...

    quartz 1.6 源码

    Quartz是Java领域的一款强大的开源任务调度框架,它允许开发者创建、组织和执行定时任务。在版本1.6中,Quartz提供了稳定的...无论是对于初学者还是经验丰富的开发者,Quartz 1.6的源码分析都是一个宝贵的教育资源。

    Quartz 开发指南(附源码)

    本指南将深入探讨 Quartz 的核心概念、配置与使用方法,并提供源码分析,帮助开发者更高效地利用这一强大工具。 1. **Quartz 基本概念** - **Job**:Job 是实际要执行的任务,是一个实现了 `org.quartz.Job` 接口...

    Quartz.NET 官方源码

    源码分析还可以帮助我们了解其事件机制,例如`SchedulerListener`和`JobListener`接口,它们允许用户在特定的调度或作业执行事件上进行自定义操作。 最后,Quartz.NET提供了丰富的API和配置选项,使得开发者可以...

    Quartz集群配置和示例源码

    示例源码分析** 在提供的压缩包中,可能包含了一个简单的Quartz集群应用示例,源码通常会包括以下部分: - **Job类**:实现`org.quartz.Job`接口,定义具体的任务逻辑。 ```java public class MyJob implements ...

    quartz-1.6.4.源码

    源码分析可以帮助我们深入理解其内部机制,从而更好地利用或定制这个强大的工具。 首先,`checkstyle.ant` 文件是 Checkstyle 配置文件,Checkstyle 是一个静态代码分析工具,用于确保代码遵循特定的编码规范。通过...

    quartz-3.0.3.1_quartes_源码.zip

    这个压缩包 "quartz-3.0.3.1_quartes_源码.zip" 包含了 Quartz 框架的源代码,版本为 3.0.3.1,对于学习和理解 Quartz 的工作原理以及进行定制化开发非常有帮助。 Quartz 主要功能包括: 1. **作业调度**:Quartz ...

    quarz 源码

    Quartz 源码分析可以帮助我们深入理解其内部的工作机制,以便更好地利用它来实现定时任务的管理。 1. **Quartz 的核心组件** - **Scheduler**: 调度器是 Quartz 的核心,负责调度所有的工作任务。它负责创建 Job ...

    quartz-1.4.5以及源码

    学习Quartz源码可以帮助我们优化任务调度策略,解决可能出现的问题,以及更好地集成到现有的系统中。对于维护老系统来说,理解源码可以提供更深层次的支持,避免因版本升级可能带来的不兼容问题。

    Quartz.NET定时任务源码(转)

    6. **源码分析**:解压后的文件包括解决方案文件(sln)和库文件,例如`Quartz.2003.sln`、`Quartz.2008.sln`,这些都是Visual Studio的项目文件,用于在开发环境中打开和编译源码。`bin`目录包含编译后的库和程序,...

    官方Quartz.NET 2.3.1 源码+15个示例

    源代码分析: 源代码的结构通常包括以下几个部分: 1. `src`目录:这是核心源代码所在的地方,包含各种服务类、接口和实现,如JobStore(存储作业和触发器的实现)、Scheduler(调度器)以及Trigger(触发器)等。...

    quartz定时器源码jar包下载

    6. **并发与线程管理**:Quartz在多线程环境下运行,分析`org.quartz.core.QuartzSchedulerThread`,了解其内部调度机制。 7. **插件系统**:Quartz有一个强大的插件系统,如`org.quartz.plugins.history....

    quartz-2.1.7 官方jar包源码

    源码分析对于理解Quartz的工作原理至关重要。在Quartz-2.1.7源码中,你可以看到如下关键组件: 1. `org.quartz.core` 包:这是Quartz的核心模块,包含Scheduler、JobStore和ThreadPool的主要实现。SchedulerImpl是...

    .net Quartz 任务调度平台源码

    《.NET Quartz 任务调度平台源码解析与应用》 .NET Quartz 是一款强大的任务调度框架,它为.NET开发者提供了一种高效、灵活的方式来安排和执行周期性任务。Quartz.NET 是开源项目Quartz的.NET版本,它允许开发人员...

    quartz-master.zip

    Quartz是一款开源的作业调度框架,它允许程序创建和管理定时任务。在Java开发中,Quartz被广泛用于...此外,对于希望参与开源项目或者对任务调度有深入需求的开发者,理解并可能贡献Quartz源码将是一次宝贵的学习经历。

    IOS应用源码——QuartzDemo.rar

    QuartzDemo是一个针对iOS平台的源码示例项目,它主要展示了如何使用Quartz 2D...通过分析和学习这些代码,开发者能够深入理解Quartz 2D的工作原理,并将其应用到自己的iOS项目中,创造出更加丰富的用户界面和图形效果。

Global site tag (gtag.js) - Google Analytics