学习使用Java Quartz任务调度(一)

学习使用Java Quartz任务调度(一)//本着以交流经验和学习的态度来分享知识,如果有误,请批评指出,不胜感激!现在企业中基本均有涉及到任务调度和异步执行器,在Java方向,提供了开源的Quartz、JDK提供了Timer。在以上基础前提下,Java5.0通过java.util.concurrent这个新包以及它下边的诸多类和接口,提供了方便的线程池调用。在本篇文章中,我们主要使用Quartz来作为解决任务调度的工具。为什么不…

大家好,又见面了,我是你们的朋友全栈君。

//本着以交流经验和学习的态度来分享知识,如果有误,请批评指出,不胜感激!

现在企业中基本均有涉及到任务调度和异步执行器,在Java方向,提供了开源的Quartz、JDK提供了Timer。在以上基础前提下,Java5.0通过java.util.concurrent这个新包以及它下边的诸多类和接口,提供了方便的线程池调用。

在本篇文章中,我们主要使用Quartz来作为解决任务调度的工具。为什么不是用JDK提供的方法?

//(因为Timer解决基础的调度室没有问题的,但是如果处理复杂逻辑调度和类似于每个星期一12:00处理任务,这种复杂时间,就有点捉急了)。

废话不多说,我们先做一个‘简单’的Quartz Demo来’简单’介绍一下Quartz的基本使用方法和功能

我先简单介绍一下Quartz的核心接口和类(如果已经了解的请略过):

1.Job,这是一个接口,并且只有一个void execute(JobExecutionContext context) throws JobExecutionException 的方法。这个方法定义了需要调度的方法,开发者在使用Quartz并定义调度任务时候,需要实现这个接口并且重写此方法。

2.JobDetail,看名字也知道这是Job的实现类,当Quartz执行Job时,它会接受JobDetail这个实现类,通过newInstance()的反射调用机制来实例化一个Job,也就是说,在实例化Job时,需要有一个返回值来接受实例化的Job和一些静态信息。

3.Trigger,这是一个类,包括两个子类,主要是触发Job执行的时间触发规则,主要有SimpleTrigger和CronTrigger两个子类;当仅需要触发一次或者以固定检核周期性执行时,SimpleTrigger一定是最合适的选择,当如果要执行复杂的调度规则时,则可以使用CronTrigger。

4.Scheduler,代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,二者在Scheduler中有各自的组件、名称和组

暂时需要了解到这4样核心API,说一说我的理解就是:当你创建一个Job和Trigger之后,将这两个放到Quartz容器 Scheduler中,通过启动Scheduler来启动Job

现在,我们创建一个工程来实际使用一下

学习使用Java Quartz任务调度(一)

这个是完成后的Demo所有文件

我们一步一步来,在Maven中首先引入依赖,如下图

    <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>
  	<dependency>
  		<groupId>org.slf4j</groupId>
  		<artifactId>slf4j-log4j12</artifactId>
  		<version>1.6.6</version>
  	</dependency>

然后创建一个针对RAM存储的JOB类,这个类是Job 的实现类,在实现Job接口后需要重写execute方法,在方法中定义需要执行的任务,举个例子如下

package quartz.demo;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RAMJob implements Job{

	private Logger log = LoggerFactory.getLogger(RAMJob.class);
	
	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		
		log.info("我也不知道这个啥时候执行,反正这个是Job 的实现类");
	}

}

然后我们在创建一个类,用来执行一个简单的任务执行器,在新的类中我们使用main方法来启动执行,在执行之前,我们需要先定义一个JobDetail对象,如图:

//创建一个JobDetail
		JobDetail jobDetail = JobBuilder.newJob(RAMJob.class)
				.withDescription("调用JobDemo")
				.withIdentity("Job's name", "Job's Group")
				.build();
		log.info("描述任务:{}" + jobDetail.getDescription());

具体的任务描述和设置都已在方法中定义,不过想了解的盆友可以点开看看源码,都很简单,这里不再阐述。

在定义完Job后,我们需要再定义一个Trigger触发规则,如下:

        //创建一个trigger触发规则
		Trigger trigger = TriggerBuilder.newTrigger()
				.withDescription("创建一个Trigger触发规则")
				.startAt(new Date())
				.withIdentity("Trigger's Name", "Trigger's Group")
				.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(10,5))
				.build();

这里可能很多没看源码的人看不懂或者是别的情况,我简单解释一下各个方法的作用,我们通过TriggerBuilder新建一个TriggerBuilder对象,

.withDescription(String description);根据字面意思,这个方法表示针对这个Trigger进行描述;

.startAt(Date triggerStartTime):根据字面单词意思,这就是设置Trigger规则启动时间的方法;

.withIdentity();这个方法是设置Trigger基本信息的方法,通过源码我们可以看到有三个重载的方法,分别是:.withIdentity(String name);.withIdentity(String name , String group);.withIdentity(TriggerKey triggerKey),这三个方法的本身操作其实是无差别的,都是要给初始化给TriggerKey对象赋值;

在完成上面两个基本任务后,我们开始构建Quartz容器,要注意一点,Quartz容器(Scheduler)是独立运行的,Scheduler可以将Trigger绑定到某一个JobDetail上,当Trigger被触发时,对应的Job就被执行,一个Job可以对应多个Trigger,一个Trigger只能对应一个Job,我们一般通过SchedulerFactory创建一个Scheduler实例;如下图:

        //创建一个调度器,也就是一个Quartz容器
        //声明一个scheduler的工厂schedulerFactory
		SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        //通过schedulerFactory来实例化一个Scheduler
		Scheduler scheduler = schedulerFactory.getScheduler();
        //将Job和Trigger注册到scheduler容器中
		scheduler.scheduleJob(jobDetail,trigger);

最后,我们启动scheduler容器:

    //启动容器
    log.info("JOB开始启动);
    ​
    scheduler.start();

​

此时我们就完全启动了一个任务异步执行,启动日志如下:

10:22:35,093 [main] INFO  quartz.demo.SimpleTriggerTest  - Job开始执行
10:22:35,099 [main] INFO  quartz.demo.SimpleTriggerTest  - 描述任务:{}调用JobDemo
10:22:35,167 [main] INFO  com.mchange.v2.log.MLog  - MLog clients using log4j logging.
10:22:35,458 [main] INFO  com.mchange.v2.c3p0.C3P0Registry  - Initializing c3p0-0.9.1.1 [built 15-March-2007 01:32:31; debug? true; trace: 10]
10:22:35,482 [main] INFO  org.quartz.impl.StdSchedulerFactory  - Using default implementation for ThreadExecutor
10:22:35,494 [main] INFO  org.quartz.core.SchedulerSignalerImpl  - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
10:22:35,495 [main] INFO  org.quartz.core.QuartzScheduler  - Quartz Scheduler v.2.2.1 created.
10:22:35,496 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX  - Using thread monitor-based data access locking (synchronization).
10:22:35,496 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX  - JobStoreTX initialized.
10:22:35,497 [main] INFO  org.quartz.core.QuartzScheduler  - Scheduler meta-data: Quartz Scheduler (v2.2.1) 'dufy_test' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is not clustered.

10:22:35,497 [main] INFO  org.quartz.impl.StdSchedulerFactory  - Quartz scheduler 'dufy_test' initialized from default resource file in Quartz package: 'quartz.properties'
10:22:35,497 [main] INFO  org.quartz.impl.StdSchedulerFactory  - Quartz scheduler version: 2.2.1
10:22:35,531 [main] INFO  com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource  - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1bqrhg09w1in8fcy1gr7r0t|39a054a5, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bqrhg09w1in8fcy1gr7r0t|39a054a5, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://140.143.205.128:3306/c_test?characterEncoding=utf8&useSSL=true, lastAcquisitionFailureDefaultUser -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 10, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
10:22:36,368 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX  - Freed 0 triggers from 'acquired' / 'blocked' state.
10:22:36,412 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX  - Recovering 0 jobs that were in-progress at the time of the last shut-down.
10:22:36,412 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX  - Recovery complete.
10:22:36,434 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX  - Removed 0 'complete' triggers.
10:22:36,455 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX  - Removed 0 stale fired job entries.
10:22:36,497 [main] INFO  org.quartz.core.QuartzScheduler  - Scheduler dufy_test_$_NON_CLUSTERED started.
10:22:36,497 [main] INFO  quartz.demo.SimpleTriggerTest  - Job结束
10:22:36,891 [dufy_test_Worker-1] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:22:40,273 [dufy_test_Worker-2] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:22:45,273 [dufy_test_Worker-3] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:22:50,269 [dufy_test_Worker-4] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:22:55,274 [dufy_test_Worker-5] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:23:00,275 [dufy_test_Worker-6] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:23:05,269 [dufy_test_Worker-7] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:23:10,272 [dufy_test_Worker-8] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:23:15,404 [dufy_test_Worker-9] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类
10:23:20,365 [dufy_test_Worker-10] INFO  quartz.demo.RAMJob  - 我也不知道这个啥时候执行,反正这个是Job 的实现类

从日志中我们可以看出,任务是以每5s的频率执行的,执行了10个周期,与上边的定义.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(10,5))的一致,任务结束

 

到此,一个基本的Quartz任务调度demo就结束了,下一期我们继续讲解Quartz与Spring的整合

谢谢!!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/158525.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • FEC算法_粒子群算法

    FEC算法_粒子群算法基于IP的语音和视频通话业务为了实时性,一般都是采用UDP进行传输,基站无线一般配置UM模式的RLC承载,因此丢包是不可避免的,在小区信号的边沿则丢包率会更高;为了通话的实时性,一般不会采用接收端发现丢包了然后通知发送端重传的机制,因为这个在应用层的丢包检测和通知发送端重传是非常耗时的。引入前向纠错(FEC)机制是解决实时通话业务丢包的一个很好的机制,FEC的原理就是在发送端发送数据包时插入冗余包…

  • VL53L0X+stm32激光测距

    VL53L0X+stm32激光测距文末有补充这段时间很忙,一直没时间看邮件,忽略了一些信息,没有及时给有需要的网友发工程代码。其实你们可以找在底下留言的网友,他们留了邮箱,加他们qq或者发邮件给他们,让他们发给你们,这样可以节省你们得时间。———2019.7.3最近学习stm32单片机,用VL53L0X这个传感器进行开发,花了不少时间和精力,写这个博客一个是为了记录自己的学习过程另外一个是感谢网上各位…

  • BoundsChecker 使用方法[通俗易懂]

    1前言我在本文中详细介绍了测试工具NuMegaDevpartner(以下简称NuMega)的使用方法。NuMega是一个动态测试工具,主要应用于白盒测试。该工具的特点是学习简单、使用方便、功能有效。NuMega共有三个独立的子功能——BoundsChecker、TrueCoverage、TrueTime。BoundsChecker为代码检错工具,TrueCoverage为测试覆盖率统计…

  • redis和jedis区别_redis和数据库的区别

    redis和jedis区别_redis和数据库的区别Redis与Spring的整合一般分为spring-data-redis和jedis整合,两者的区别在于:1.引入的依赖不同spring-data-redis引入的是<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId></dependency>jedis引入的是:&

  • lseek 出错

    lseek 出错学习windows游戏编程大师时,运行加载位图的函数出错intLoad_Bitmap_File(BITMAP_FILE_PTRbitmap,char*filename) 网上搜的答案 其实这个函数之所以失败是因为你使用的编译器问题,如果你使用vc6就没问题,问题是这样的,像OpenFile,_lseek等这样的函数是16位windows时期的文件操作函数,在vc中它的运

  • 推荐自学python必入的神仙网站

    推荐自学python必入的神仙网站现在没点技术,工作想要6000+太难了,想要挣钱,就必须让自己值钱,想要自学python必知的网站分享,每一个网站上都有自学的文章和教程,不花一分钱,自学python入门,为自己增值。1、什么是Py

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号