以往写任务调度,碰到秒级任务调度,必不可免的使用sleep来做延时。
在实际操作中非常不方便,而且因为任务本身存在执行时间问题,必不可免的造成不准确的sleep。搜索了下网上相关开源框架,发现Quartz最适合我的任务场景的应用。可惜本身JAVA语言并不是很好,又无奈英文水平有限,磕磕碰碰遇到很多问题。
在IDE部分,选用Eclipse4.5+jdk1.8。框架部分,选用Quartz2.2.3。
网上大多例子均不是基于2.2.3的导致函数方法上存在差异,无法执行。而且略微复杂的功能框架javadoc内均没详细说明,例子也没写清楚。一个简单运行例子。
package Test;
import java.util.Date;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.JobKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class QuartzManager {
private static Logger log = LoggerFactory.getLogger(QuartzManager.class);
private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
public void run() throws Exception {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
// 新建任务 任务名,任务组,任务执行类
JobDetail jobDetail = newJob(HelloJob.class).withIdentity("jobName, "jobGroupName")
.build();
// 触发器 cron格式每秒执行
CronTrigger trigger = newTrigger().withIdentity("triggerName", "triggerGroupName")
.withSchedule(cronSchedule("0/1 * * * * ?"))
.build();
// 任务绑定触发器
sched.scheduleJob(jobDetail, trigger);
// 启动
if (!sched.isShutdown()) {
sched.start();
}
// 延时10秒
Thread.sleep(10L * 1000L);
// 实际引用中大家一般不会直接getKey所以例子内用字符串转换方式
// 这个地方坑了我至少2小时,网上例子里均是直接使用字符串的
// 但是2.2.3内参数类型为JobKey和TriggerKey
// 获取 JobKey
JobKey jobKey =new JobKey("jobName","jobGroupName");
// 获取 TriggerKey
TriggerKey triggerKey =new TriggerKey("triggerName","triggerGroupName");
// 停止触发器
sched.pauseTrigger(triggerKey);
// 停止任务
sched.pauseJob(jobKey);
// 删除任务
sched.deleteJob(jobKey);
} catch (Exception e) {
throw new RuntimeException(e);
}
public static void main(String[] args) throws Exception {
QuartzManager example = new QuartzManager();
example.run();
}
}
package Test;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class HelloJob implements Job {
private static Logger _log = LoggerFactory.getLogger(HelloJob.class);
public HelloJob() {
System.out.println("Hello World! - " + new Date());
}
public void execute(JobExecutionContext context)
throws JobExecutionException {
_log.info("Hello World! - " + new Date());
}
}
因为使用了slf4j,所以一定要在bin目录放置log4j.xml,配置信息如下:
如果想使用数据库来持久化任务的话,可以用框架源码下的docs\dbTables目录内的sql自己创建数据库。
以mysql为例子,Quartz需要使用InnoDb请使用tables_mysql_innodb.sql而并不是tables_mysql.sql,除非你的数据库默认不是MyISAM。
然后在导入成功后,在项目内引用mysql-connector-java库,再在bin目录增加配置文件quartz.properties内容如下。
org.quartz.scheduler.instanceName = Test
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = myDS
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/task?characterEncoding=utf-8
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = 123456
org.quartz.dataSource.myDS.maxConnections = 5