Quartz的使用浅析

一、Quartz引入背景

假定在业务逻辑中存在一个这样的需求,“每天的午夜12点,进行一次网络请求操作之后,将操作的结果写入数据库中”。针对这一需求,很简单明了的解决方案,在代码中引入一个定时间,定时的时间设置在午夜12点,该问题似乎被完美的解决了。但是如果将Java的Jar包程序进行分布式部署之后,你会发现整个业务逻辑中,进行了多次网络请求,然后写入了多次数据库。此时你就会想到,在整个业务逻辑中存在多个jar包,每一个Jar包中都存在定时器,所以定时任务被同时执行了多次。如果要整个业务逻辑中实现上述需求,则可以使用Quartz来进行解决该问题。

二、Quartz的基本概念

在介绍Quartz的使用前,先需要了解一下Quartz如下基本概念。
Job(任务) :job是被实际调度的任务,每个任务必须指定具体执行任务的实现类,实现类需要继承QuartzJobBean(Spring框架)或者实现org.quartz.Job接口,具体的业务逻辑定义在execute方法中。是否支持并发的注解,@DisallowConcurrentExecution。
JobDetail:JobDetail表示一个具体的可执行的调度程序,Job是这个可执行调度程序要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略。
tigger(触发器) : trigger用来定义调度时间的概念,即按什么样时间规则去触发任务,可以分为以下几种类型。
SImpleTrigger:简单触发器,从某个时间开始,每隔多少时间触发,重复多少次。
CronTrigger:使用cron表达式定义触发得时间规则,如"0 0 0,2,4 1/1 * ? *" 表示每天的0,2,4点触发。
DailyTimeIntervalTrigger:每天中的一个时间段,每N个时间单元触发,时间单元可以是毫秒,秒,分,小时。
CalendarIntervalTrigger:每N个时间单元触发,时间单元可以是毫秒,秒,分,小时,日,月,年。
Scheduler(调度器):代表一个调度器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了。
Quartz数据表
qrtz_blob_triggers,以Blob类型存储的触发器。
qrtz_calendars,存放日历信息,quartz可配置一个日历来指定一个时间范围。
qrtz_cron_triggers,存放cron类型的触发器。
qrtz_fired_triggers,存放已触发的触发器。
qrtz_job_details,存放一个jobDetail信息。
qrtz_locks,存储程序的悲观锁信息(假如使用了悲观锁)
qrtz_paused_trigger_graps,存放暂停掉的触发器
qrtz_scheduler_state,调度器状态
qrtz_simple_triggers,简单触发器的信息
qrtz_trigger_listeners,触发器监听器
qrtz_triggers,触发器的基本信息
如果使用cron方式时需要用到的4张数据表:
qrtz_triggers、qrtz_cron_triggers、qrtz_fired_triggers、qrtz_job_details

三、Quartz在Spring中的使用范例

3.1 构建数据库

下载quartz的数据库构建表,下载地址 ,下载后解压,运行tables_mysql_innodb.sql创建表(解压后如在D:\软件\quartz-2.2.3-distribution\quartz-2.2.3\docs\dbTables下)

3.2 pom中添加依赖

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

3.3 代码编写

//定义Quartz的Job类
public class MyQuartzJobBean2 extends QuartzJobBean {
    protected Logger logger = LoggerFactory.getLogger(MyQuartzJobBean2.class);
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        // TODO Auto-generated method stub
        logger.info("....execute2:{}....", context.getTrigger().getKey());
    }
}
//定义一个Scheduler配置类,用于构建Scheduler
@Configuration
public class SchedulerConfig {
    @Autowired
    private DataSource dataSource;
    /**
     * 调度器
     * @return
     * @throws Exception
     */
    @Bean
    public Scheduler scheduler() throws Exception {
        Scheduler scheduler = schedulerFactoryBean().getScheduler();
        return scheduler;
    }

    /**
     * Scheduler工厂类
     * @return
     * @throws IOException
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setSchedulerName("Cluster_Scheduler");
        factory.setDataSource(dataSource);
        factory.setApplicationContextSchedulerContextKey("applicationContext");
        factory.setTaskExecutor(schedulerThreadPool());
        factory.setQuartzProperties(quartzProperties());
        factory.setStartupDelay(10);//延迟10s执行
        return factory;
    }

    /**
     * 加载配置属性
     * @return
     * @throws IOException
     */
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/spring-quartz.properties"));
        // 在quartz.properties中的属性被读取并注入后再初始化对象
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    /**
     * schedule配置线程池
     * @return
     */
    @Bean
    public Executor schedulerThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors());
        executor.setQueueCapacity(Runtime.getRuntime().availableProcessors());
        return executor;
    }
}
try {
		//根据Job创建Quartz的JobDetail
		Class clazz = MyQuartzJobBean.class;
		JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity("job1", "test_job").build();
		//创建scheduler
		scheduler = schedulerConfig.scheduler();
		//创建一个CronTrigger
		TriggerKey triggerKey = TriggerKey.triggerKey("trigger1", TRIGGER_GROUP_NAME);
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		//在sheduler中配置JobDetail和trigger,并进行启动
		scheduler.scheduleJob(jobDetail, trigger);
		scheduler.start();
	} catch (Exception e) {
		log.info(ExceptionUtils.getFullStackTrace(e));
	}

参考文献

1.深入解读Quartz的原理
2.Quartz学习详解
3.Spring Quartz 实现原理与示例
4.Quartz集群原理分析-基于数据库行锁实现负载均衡
5.springboot-整合quartz:做分布式定时任务

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值