Java任务调度之Quartz快速入门

原创 2016年08月31日 11:15:08

首先所谓的任务调度指的是软件系统在从某个时间节点开始,以固定的频率,除去特定的某些时间段,定期执行某项任务,比如可以在某个夜深人静的时候做一些大批量的文件传输、备份等耗费极大资源的工作,那么通过这个概念可以引出任务调度中的四个核心:

1、时间相关,即如何设定什么时候开始、如何排除特定时间、如何设定频率等;

2、执行任务相关,到时间后,程序要干什么工作呢?

3、谁来调度任务?即如何将上述1和2关联起来,然后分配相应的各式资源进行任务调度;

4、如果任务调度过程中,出现程序异常中断,那么后续任务如何回复?

基本上,任务调度的各种框架都围绕着上述四个核心展开,另外本次本次讲解将会用到以下MAVEN依赖:

	<dependency>
		<groupId>org.quartz-scheduler</groupId>
		<artifactId>quartz</artifactId>
		<version>2.2.2</version>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.38</version>
	</dependency>
示例代码:

package com.quartz.samples.example1;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/*
 * Quartz中,开发者需要实现该接口并实现execute(JobExecutionContext context),在方法中定义需要执行的任务;
 * 该方法会传入JobExecutionContext类型的对象,该对象封装了调度上下文中各种信息
 */
public class HelloJob implements Job{
	
	public HelloJob() {
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		System.out.println("HelloJob任务得到执行,执行时间为:" + new Date().toLocaleString());
	}
}

package com.quartz.samples.example1;

import java.util.Date;

import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class SimpleExample {

	@SuppressWarnings("deprecation")
	public void run() throws SchedulerException {

		// 获取任务调度器
		StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
		Scheduler scheduler = stdSchedulerFactory.getScheduler();

		// 定义一个JobDetail对象,并将它与HelloJob类进行绑定
		JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

		// 构建距离现在下一个偶数分钟时间
		Date startDate = DateBuilder.evenMinuteDateAfterNow();

		// 在下一个偶数分钟出发任务执行
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(startDate).build();

		// 告诉quartz,用自定义规则触发器去调度任务
		scheduler.scheduleJob(jobDetail, trigger);

		// 启动任务调度器
		scheduler.start();
		System.out.println("任务将要在" + startDate.toLocaleString()+ "得到执行!!");

		// 然后让程序睡眠几秒钟,以便让我们的任务调度器有充足的时间去执行任务
		try {
			Thread.sleep(65L * 1000L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 停止任务调度器
		scheduler.shutdown(true);
	}

	public static void main(String[] args) throws SchedulerException {
		SimpleExample example = new SimpleExample();
		example.run();
	}
}
输出结果:


通过上述示例可以发现在Quartz任务调度框架中用:

1、Trigger接口及所有该接口实现类来解决上述核心1

2、JobDetail、Job及实现类来解决上述核心2

3、Scheduler类来解决上述核心3

下面我们来看看Trigger,它是一个类,用来描述Job执行的时间触发规则。主要有两个子类:SimpleTrigger和CronTrigger;当仅需要出发一次或者以固定间隔周期性执行时SimpleTrigger是最佳选择,CronTrigger则通过Cron表达式定义出各种复杂任务方案;

好的,先通过一个简单例子来实现15秒后开启一个任务调度,每隔5秒钟执行一次,总共执行20次,Job实现类内容不变,看代码:

package com.quartz.samples.example2;

import java.util.Date;

import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class SimpleTriggerExample {

	@SuppressWarnings("deprecation")
	public void run() throws SchedulerException {

		// 获取任务调度器
		StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
		Scheduler scheduler = stdSchedulerFactory.getScheduler();

		// 定义一个JobDetail对象,并将它与HelloJob类进行绑定
		JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

		// 15s后的时间节点
		Date startDate = DateBuilder.nextGivenSecondDate(null, 15);

		// 在15s后开始,每隔5s执行一次,总共执行20次
		SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(20).withIntervalInSeconds(5)).startAt(startDate).build();

		// 告诉quartz,用自定义规则触发器去调度任务
		scheduler.scheduleJob(jobDetail, trigger);

		// 启动任务调度器
		scheduler.start();
		System.out.println("任务将要在" + startDate.toLocaleString()+ "得到执行!!");

		// 然后让程序睡眠几秒钟,以便让我们的任务调度器有充足的时间去执行任务
		try {
			Thread.sleep(350L * 1000L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 停止任务调度器
		scheduler.shutdown(true);
	}

	public static void main(String[] args) throws SchedulerException {
		SimpleTriggerExample example = new SimpleTriggerExample();
		example.run();
	}
}
部分执行结果如下:


可以看到该类通过with(ScheduleBuilder<SBT> schedBuilder)来指定执行次数和时间间隔,感兴趣的可以继续研究一下源码,研究完SimpleTrigger类,咱们再来看一下CronTrigger类的用法,可以这么说在企业级应用里面用的最多的也是这个,因为它可以实现复杂任务调度工作,看一个简单CRON示例:

package com.quartz.samples.example3;

import java.util.Date;

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

public class SimpleJob implements Job {

    public SimpleJob() {
    }

    public void execute(JobExecutionContext context)
        throws JobExecutionException {

        JobKey jobKey = context.getJobDetail().getKey();
        
        System.out.println("SimpleJob says: " + jobKey + " executing at " + new Date());
    }
}

package com.quartz.samples.example3;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.examples.example3.SimpleJob;
import org.quartz.impl.StdSchedulerFactory;

public class CronTriggerExample {

	@SuppressWarnings("deprecation")
	public void run() throws SchedulerException {

		// 获取任务调度器
		StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
		Scheduler sched = stdSchedulerFactory.getScheduler();

		// job1将会在每隔20秒执行一次
		JobDetail job = JobBuilder.newJob(SimpleJob.class).withIdentity("job1", "group1").build();
		CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1")
				.withSchedule(CronScheduleBuilder.cronSchedule("0/20 * * * * ?")).build();

		Date ft = sched.scheduleJob(job, trigger);
		System.out.println(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
				+ trigger.getCronExpression());

		// job 2 将每隔两分钟,执行时间为15s执行
		job = newJob(SimpleJob.class).withIdentity("job2", "group1").build();

		trigger = newTrigger().withIdentity("trigger2", "group1")
				.withSchedule(CronScheduleBuilder.cronSchedule("15 0/2 * * * ?")).build();

		ft = sched.scheduleJob(job, trigger);
		System.out.println(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
				+ trigger.getCronExpression());

		// job 3 将在上午8点到下午5点,每隔两分钟执行一次
		job = newJob(SimpleJob.class).withIdentity("job3", "group1").build();

		trigger = newTrigger().withIdentity("trigger3", "group1")
				.withSchedule(CronScheduleBuilder.cronSchedule("0 0/2 8-17 * * ?")).build();

		ft = sched.scheduleJob(job, trigger);
		System.out.println(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
				+ trigger.getCronExpression());

		// job 4 将在下午5点到11点,每隔3分钟执行一次
		job = newJob(SimpleJob.class).withIdentity("job4", "group1").build();

		trigger = newTrigger().withIdentity("trigger4", "group1")
				.withSchedule(CronScheduleBuilder.cronSchedule("0 0/3 17-23 * * ?")).build();

		ft = sched.scheduleJob(job, trigger);
		System.out.println(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
				+ trigger.getCronExpression());

		// job 5 将每月的1号、15号,每天上午10点执行
		job = newJob(SimpleJob.class).withIdentity("job5", "group1").build();

		trigger = newTrigger().withIdentity("trigger5", "group1")
				.withSchedule(CronScheduleBuilder.cronSchedule("0 0 10am 1,15 * ?")).build();

		ft = sched.scheduleJob(job, trigger);
		System.out.println(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
				+ trigger.getCronExpression());

		// job 6 将在每周周一到周五,在每分钟的0s和30秒执行
		job = newJob(SimpleJob.class).withIdentity("job6", "group1").build();

		trigger = newTrigger().withIdentity("trigger6", "group1")
				.withSchedule(CronScheduleBuilder.cronSchedule("0,30 * * ? * MON-FRI")).build();

		ft = sched.scheduleJob(job, trigger);
		System.out.println(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
				+ trigger.getCronExpression());

		// job 7 将只在每周的周六周天,在每分钟的0s和30秒执行一次
		job = newJob(SimpleJob.class).withIdentity("job7", "group1").build();

		trigger = newTrigger().withIdentity("trigger7", "group1")
				.withSchedule(CronScheduleBuilder.cronSchedule("0,30 * * ? * SAT,SUN")).build();

		ft = sched.scheduleJob(job, trigger);

		// 启动任务调度器
		sched.start();
		
		// 等待300s展示结果
		try {
			Thread.sleep(300L * 1000L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 停止任务调度器
		sched.shutdown(true);
	}

	public static void main(String[] args) throws SchedulerException {
		CronTriggerExample example = new CronTriggerExample();
		example.run();
	}
}
运行结果就不贴出来了,大家自行复制演示,可以看得出CRON就是用来解决各种复杂时间段的任务类型的;

现在有如下一个需求:想要实现在每周的一、三、五的每天晚上11:30执行某个定时任务,但是要去除某个节假日,比如每年的五一、十一这个该怎么实现呢?看示例:

package com.quartz.samples.example4;

import static org.quartz.DateBuilder.dateOf;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.examples.example3.SimpleJob;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.AnnualCalendar;

public class CalendarExample {

	@SuppressWarnings("deprecation")
	public void run() throws SchedulerException {

		// 获取任务调度器
		StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
		Scheduler sched = stdSchedulerFactory.getScheduler();
		
		// 构建所有日期对象集合
	    AnnualCalendar holidays = new AnnualCalendar();

	    // 劳动节 5月1日 
	    Calendar firstOfMay = new GregorianCalendar(2016, 4, 1);
	    holidays.setDayExcluded(firstOfMay, true);
	    
	    // 国庆节 10月1日
	    Calendar nationalDay = new GregorianCalendar(2016, 9, 1);
	    holidays.setDayExcluded(nationalDay, true);

	    // tell the schedule about our holiday calendar
	    sched.addCalendar("holidays", holidays, false, false);

	    // 10月1日上午十点启动任务调度
	    Date runDate = dateOf(0, 0, 10, 1, 10);

	    // job1将会在每周一、三、五的每天晚上11:30得到执行
	    JobDetail job = JobBuilder.newJob(SimpleJob.class).withIdentity("job1", "group1").build();
	    CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1")
	    		.withSchedule(CronScheduleBuilder.cronSchedule("0 30 11pm ? * MON,WED,FRI")).modifiedByCalendar("holidays").startAt(runDate).build();

	    // schedule the job and print the first run date
	    Date firstRunTime = sched.scheduleJob(job, trigger);

	    // print out the first execution date.
		sched.scheduleJob(job, trigger);

		// 启动任务调度器
		sched.start();
		
		// 等待300s展示结果
		try {
			Thread.sleep(300L * 1000L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 停止任务调度器
		sched.shutdown(true);
	}

	public static void main(String[] args) throws SchedulerException {
		CalendarExample example = new CalendarExample();
		example.run();
	}
}
通过上述方式,就可以选中排除非工作日了,还算是挺好理解的吧;

最后再看一下任务调度的信息存储,在默认情况下,Quartz将任务调度的运行信息保存在内存中,这种方式在提供了良好性能的同时,缺乏数据的持久性;比如说,我们执行了一个需要执行100次的任务,运行期间执行到50次,突然系统崩溃了,如果这个时候重新启动的话,计数器就会从0开始。虽然在实际应用中很少需要一个指定次数的执行任务,但是如果确实需要持久化任务调度信息,Quartz允许用户通过调整属性文件,将这些任务调度信息保存到数据库中,使用数据库保存任务调度信息后,即便系统崩溃后重新启动,任务调度的信息将得以恢复,闭上上述例子将从51次开始,首先来认识一下org.quartz包下面的quartz.properties文件,文件内容如下:

# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#

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: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000

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

在该配置文件的最后一行,发现原来quartz将任务调度信息保存在RAM中是在这里规定的,那么也就是说如果我们想将任务调度信息保存到数据库中需要修改org.quartz.jobStore.class属性值以及添加部分属性,首先创建任务调度信息存储必要的11张表,这些数据库表的创建信息由quartz提供,创建完毕后会有如下表:


接下来类路径下面新建一个quartz.properties,一旦创建该文件后,会将org.quartz包下面的quartz.properties覆盖,在创建该文件时,要提供完整的配置信息,否则在运行时会抛出各种异常,看配置完成后的文件内容:

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================

org.quartz.scheduler.instanceName: TestScheduler
org.quartz.scheduler.instanceId: AUTO

org.quartz.scheduler.skipUpdateCheck: true

#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 3
org.quartz.threadPool.threadPriority: 5

#============================================================================
# Configure JobStore  
#============================================================================


org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties: false
org.quartz.jobStore.dataSource: myDS
org.quartz.jobStore.tablePrefix: QRTZ_
org.quartz.jobStore.isClustered: false

#============================================================================
# Configure Datasources  
#============================================================================

org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL: jdbc:mysql://localhost:3306/quartz
org.quartz.dataSource.myDS.user: root
org.quartz.dataSource.myDS.password: root
org.quartz.dataSource.myDS.maxConnections: 5
然后运行下面这个例子,等任务调度两次后,强制终止JVM执行,来模拟程序运行过程中中断、崩溃情况:

package com.quartz.sample.sample2;

import java.util.Date;

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

public class SimpleJob implements Job {

    public SimpleJob() {
    }

    public void execute(JobExecutionContext context)
        throws JobExecutionException {

        // This job simply prints out its job name and the
        // date and time that it is running
        JobKey jobKey = context.getJobDetail().getKey();
        System.out.println("SimpleJob says: " + jobKey + " executing at " + new Date());
    }

}
package com.quartz.sample.sample2;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.Date;

import org.quartz.DateBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;

public class SimpleTriggerExample {

	public void run() throws Exception {
		// First we must get a reference to a scheduler
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler sched = sf.getScheduler();

		// get a "nice round" time a few seconds in the future...
		Date startTime = DateBuilder.nextGivenSecondDate(null, 15);

		// job1 will run 11 times (run once and repeat 10 more times)
		// job1 will repeat every 10 seconds
		JobDetail job = newJob(SimpleJob.class).withIdentity("job1", "group1").build();

		SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
				.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10)).build();

		sched.scheduleJob(job, trigger);
		
		sched.start();

		try {
			// wait 33 seconds to show jobs
			Thread.sleep(30L * 1000L);
			// executing...
		} catch (Exception e) {
			//
		}
		sched.shutdown(true);
	}

	public static void main(String[] args) throws Exception {

		SimpleTriggerExample example = new SimpleTriggerExample();
		example.run();

	}
}
运行上述程序终止后,会发现在数据库表里会有好多条运行信息,我刚刚是在程序调度任务执行两次后终止的程序,所有还有剩下8次需要执行,来看看如何回复程序运行,上一个简单示例代码:

package com.quartz.sample.sample2;

import java.util.List;
import java.util.Set;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;

public class JDBCJobStoreRunner {
	public static void main(String[] args) {
		try {
			StdSchedulerFactory factory = new StdSchedulerFactory();
			Scheduler schd = factory.getScheduler();
			
			List<String> groupNames = schd.getTriggerGroupNames();
			for(int i = 0; i < groupNames.size(); i++){
				Set<TriggerKey> keys = schd.getTriggerKeys(GroupMatcher.triggerGroupEquals(groupNames.get(i)));
				for(TriggerKey key : keys){
					schd.rescheduleJob(key, schd.getTrigger(key));
				}
			}
			schd.start();
			
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
运行一下会发现,执行结果为剩余的8次任务;

好了,入门知识差不多就这么多了,后续还会重点针对CRON表达式继续推出新的博客!!

java框架源码之Quartz(1):定时任务如何调度

好久没写博客啦。年底不是很忙,就把平常自己积累的东西放到博客上吧。和大家共享学习下。 quartz框架是大家常用的 定时任务框架。而定时任务在分布式异步系统中,是常用的主动轮询的手段。认清它底层怎么运...
  • wei_ya_wen
  • wei_ya_wen
  • 2015年12月12日 17:31
  • 1433

Java任务调度框架Quartz教程实例

介绍  Quartz is a full-featured, open source job scheduling service that can be integrated with, or u...
  • llhhyy1989
  • llhhyy1989
  • 2013年06月07日 11:01
  • 60880

Quartz任务调度(1)概念例析快速入门

Quartz框架需求引入 在现实开发中,我们常常会遇到需要系统在特定时刻完成特定任务的需求,在《spring学习笔记(14)引介增强详解:定时器实例:无侵入式动态增强类功能》,我们通过引介增强来简单...
  • qwe6112071
  • qwe6112071
  • 2016年03月27日 14:14
  • 3072

[译]Java定时任务调度-Quartz Cron 调度

cron是一个历史悠久的unix工具,它的调度能力无疑是很强的。CronTrigger类就是基于cron的调度能力。Cron Trigger使用cron表达式,可以创建诸如“周一到周五的上午八点”或者...
  • hfut_wowo
  • hfut_wowo
  • 2017年03月09日 20:01
  • 775

[置顶] 基于zookeeper和quartz实现分布式定时调度

目的 利用zookeeper的特性,来控制quartz实现分布式调度,保证quartz的单点运行,同时解除quartz自身分布式部署对数据库的依赖,保证同一时刻只有一个quartz应用在执行任务。 ...
  • lanjian056
  • lanjian056
  • 2016年09月30日 14:54
  • 6101

Quartz+JAVA+Servlet实现任务调度系统(简洁)

1.开发环境 tomcat8.5,Jdk1.8,maven ;技术:java ,quartz,servlet(为了简便) 2.该系统使用场景:`在12306上买了一张火车票,30分钟内需要支付(需要...
  • qq_30097433
  • qq_30097433
  • 2017年03月08日 17:31
  • 793

任务调度框架Quartz(一) Quartz——一个强大的定时任务调度框架

Quartz,水晶、石英,一个简单朴素有美丽的名字,在Java程序界,Quartz大名鼎鼎,很多Java应用几乎都集成或构建了一个定时任务调度系统,Quartz是一个定时任务调度框架。 何为定时任务...
  • zixiao217
  • zixiao217
  • 2016年11月04日 00:00
  • 5429

java计划任务调度框架quartz结合spring实现调度的配置实例代码分享

java计划任务调度框架quartz结合spring实现调度的配置实例代码分享,代码下载地址:http://www.zuidaima.com/share/1755429240540160.htm...
  • yaerfeng
  • yaerfeng
  • 2014年04月26日 10:03
  • 12194

任务调度开源框架Quartz动态添加、修改和删除定时任务

Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。Quartz框架包含了调度器监听、作业和触发器监听。你可以配置作业和触发器监听为全局监听或者是特定于...
  • luo201227
  • luo201227
  • 2014年07月07日 14:50
  • 49484

使用activemq 和 quartz构建简易版企业调度中心

java定时任务框架quartz和activemq有什么关系呢?实际上我们使用activemq进行解耦用的,可以看一下简易的设计图 调度中心:上面记录各种定时任务的信息,比如我们有一个每...
  • u011325787
  • u011325787
  • 2016年05月16日 05:40
  • 2587
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java任务调度之Quartz快速入门
举报原因:
原因补充:

(最多只允许输入30个字)