文档章节

quartz2.2源码分析1-使用和原理

Small-Liu
 Small-Liu
发布于 2016/04/23 11:32
字数 803
阅读 1922
收藏 10

前言

Quartz是一款由java写成的作业调度框架,在大量javase/javaee应用中被用来做定时任务,它功能强大而又不失使用简单性。

使用例子

maven引入:

<dependency>
     <groupId>org.quartz-scheduler</groupId>
     <artifactId>quartz</artifactId>
     <version>2.2.2</version>
</dependency>

加入配置文件org/quartz/quartz.properties,使用源码包里面默认配置即可:

org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 20
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000

org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

例子代码:

调度管理类:

import java.util.HashMap;
import java.util.Map;

import org.quartz.DateBuilder;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzManager {

    private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();

    private static String HM_JOB = "HM_JOB";
    private static String HM_TRIGGER = "HM_TRIGGER";

    /**
     * 增加任务
     * @param jobClass 任务实现类
     * @param jobName 任务名称
     * @param interval 间隔时间
     * @param data 数据
     */
    public static void addJob(Class<? extends Job> jobClass, String jobName, int interval, Map<String, Object> data) {
        try {
            Scheduler sched = gSchedulerFactory.getScheduler();
            
            JobDetail jobDetail = JobBuilder.newJob(jobClass)
                            .withIdentity(jobName, HM_JOB)//任务名称和组构成任务key
                            .build();
            jobDetail.getJobDataMap().putAll(data);
            // 触发器
            SimpleTrigger trigger = TriggerBuilder.newTrigger()
                           .withIdentity(jobName, HM_TRIGGER)//触发器key
                           .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
                           .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                           .withIntervalInSeconds(interval)
                           .repeatForever())
                           .build();

            sched.scheduleJob(jobDetail, trigger);
            // 启动
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除任务 
     * 
     * @param jobName 任务名称
     */
    public static void removeJob(String jobName) {
        try {
            Scheduler sched = gSchedulerFactory.getScheduler();
            sched.deleteJob(new JobKey(jobName, HM_JOB));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

实现Job自定义任务类:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class TestJob implements Job {

    public void execute(JobExecutionContext jobexecutioncontext) throws JobExecutionException {
        String id = jobexecutioncontext.getJobDetail().getJobDataMap().getString("id");
        System.out.println("threadId: " + Thread.currentThread().getId() + ", id: " + id);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

main:

public static void main(String[] args) throws InterruptedException {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("id", "1");
    addJob(TestJob.class, "aaa", 1, map);

    map.clear();
    map.put("id", "2");
    addJob(TestJob.class, "bbb", 1, map);

    Thread.sleep(3000);
    removeJob("aaa");
    System.out.println("main end----------");
    Thread.sleep(3000);
    System.exit(1);
}

结果:

threadId: 12, id: 2
threadId: 11, id: 1
threadId: 13, id: 1
threadId: 14, id: 2
threadId: 15, id: 1
threadId: 16, id: 2
main end----------
threadId: 17, id: 2
threadId: 18, id: 2
threadId: 19, id: 2

工作原理

Quartz是通过对用户暴露出Scheduler来进行任务的操作,它可以把任务JobDetail和触发器Trigger加入任务池中,可以把任务删除,也可以把任务停止,scheduler把这些任务和触发器放到一个JobStore中,这里jobStore有内存形式的也有持久化形式的,当然也可以自定义扩展成独立的服务。

它内部会通过一个调度线程QuartzSchedulerThread不断到JobStore中找出下次需要执行的任务,并把这些任务封装放到一个线程池ThreadPool中运行,它的组件结构如下图:

1.Job就是自定义业务的接口,里面就一个execute方法,线程运行Job时会把JobDataMap封装到JobExecutionContext里作为execute方法的参数,jobdetail是对job的封装,里面有Job的class,对应的数据, 名称,分组等
2.Trigger是触发器,job下次什么时候执行存放在trigger中
3.QuartzSchedulerResources相当于调度的资源存放器,包含了JobStore, ThreadPool等资源,调度都是通过                QuartzSchedulerResources获取相关属性的。
4.jobStore是任务和触发器存储地方,它里面提供大量类似于增删改的操作任务方法。
5.QuartzSchedulerThread是一个调度线程,ThreadPool是一个执行线程池,下图是运行后的线程栈:

 

© 著作权归作者所有

共有 人打赏支持
Small-Liu
粉丝 18
博文 56
码字总数 49976
作品 0
南京
程序员
私信 提问
Android Handler异步通信:深入详解Handler机制源码

前言 在开发的多线程应用场景中,机制十分常用 今天,我将手把手带你深入分析 机制的源码,希望你们会喜欢 目录 1. Handler 机制简介 在多线程的应用场景中,将工作线程中需更新的操作信息 ...

carson_ho
2018/05/21
0
0
quartz2.2源码分析3-线程模型

quartz用一个线程不断轮询查找下次待执行的任务,并把任务交给线程池执行,这里涉及两种角色:调度线程和执行线程池 调度线程 看线程QuartzSchedulerThread的run()方法以while(true)的方式循...

Small-Liu
2016/05/13
356
0
这是一份全面 & 详细的Google序列化神器protocolBuffer 学习指南

前言 习惯用 数据存储格式的你们,相信大多都没听过 其实 是 出品的一种轻量 & 高效的结构化数据存储格式,性能比 真的强!太!多! 由于 出品,我相信已经具备足够的吸引力 今天,我将献上一...

Carson_Ho
2018/05/14
0
0
手把手带你源码分析 HashMap 1.7

前言 HashMap 在 Java 和 Android 开发中非常常见 今天,我将带来 HashMap 的全部源码分析,希望你们会喜欢。 目录 1. 简介 类定义 3. 具体使用 3.1 主要使用API(方法、函数) 3.2 使用流程...

烂猪皮
2018/04/21
0
0
Hash源码分析(JDK1.7和1.8的对比)

前言 在 和 开发中非常常见 而 相对于 更新多 今天,我将通过源码分析 ,从而讲解 相对于 的更新内容,希望你们会喜欢。 本文基于版本 ,即 关于版本 ,即 ,具体请看文章Java:手把手带你源...

瑞查德-Jack
01/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

万能的Python,还能用来制作高大上的进度条?

对于开发或者运维来说,使用Python去完成一些跑批任务,或者做一些监控事件是非常正常的情况。那么如何有效的监控任务的进度,除了在任务中加上log外,还能不能有另一种方式来了解任务进展到...

上海小胖
28分钟前
2
0
如何嵌入 HTML 到 iPython notebook的输出

如何嵌入 HTML 到 iPython notebook的输出 iPython notebook中可以嵌入 HTML,也适用于JupyterHub和JupyterLab环境。不仅可以显示常用的HTML标签文本,甚至可以嵌入脚本交互操作和Frame分隔框...

openthings
55分钟前
1
0
四、RabbitMQ3.7在CentOS7下的安装

安装依赖 sudo yum install -y gcc gcc-c++ glibc-devel make ncurses-devel openssl-devel autoconf java-1.8.0-openjdk-devel git 创建yum源 vi /etc/yum.repos.d/rabbitmq-erlang.repo [......

XuePeng77
今天
2
0
android 延长Toast的时长

示例:myToast(5000,"hello"); public void myToast(int showTime, String msg) { Toast hello = Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT); new CountDownTimer(......

雨焰
昨天
4
0
浅谈mybatis的日志适配模式

Java开发中经常用到的日志框架有很多,Log4j、Log4j2、slf4j等等,Mybatis定义了一套统一的日志接口供上层使用,并为上述常用的日志框架提供了相应的适配器。有关适配器模式例子可以参考 设计...

算法之名
昨天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部