最近项目里用到了定时任务,诚然,用多线程去定时任务也是可以的。但是最后还是采用了quartz这种方式来实现定时任务。而且,用quartz这种方式实现,具有很好的扩展性。只需要去实现具体的实现类,就可以了。下面,将把主要代码粘贴在下面:
1.首先,写一个定时任务接口:
/**
* 定时任务接口
* @author linhai
*
*/
public interface IQuartsJob {
/**
* 执行方法
* @param map
*/
public void excute(Object map);
}
后面具体的逻辑就去实现这个接口。
2.需要一个类去实现第一步的接口,代码如下:
/**
* 具体去执行定时任务的
* @author
*
*/
public class IQuartsJobImpl implements IQuartsJob {
@Override
public void excute(Object map) {
// TODO 自动生成的方法存根
/**
* 1.判断是按分钟、按小时、还是按天执行
*/
HashMap<String, Object> paramMap = (HashMap<String, Object>) map;
/**
* 具体的实现逻辑代码,请根据自己需求完善成功
*/
}
3.需要一个类去实现quartz里的接口Job,代码如下:
/**
* 任务执行器
* @author linhai
*
*/
public class QuartsJobExecutor implements Job {
/**
* 任务执行
*/
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>)context.getJobDetail().getJobDataMap().get("data");
String classpath = (String)data.get("classpath");
System.out.println("classpath : " + classpath);
try{
IQuartsJob jb=(IQuartsJob)Class.forName(classpath).newInstance();
jb.excute(data.get("data"));
}
catch(Exception e ){
e.printStackTrace();
}
}
}
以上代码通过java的反射机制去执行。通过把第二步的实现的java类的路径存储在任务执行器里,最后实现定时任务。但要实现定时任务,还需要一个启动定时任务与关闭定时任务的操作。将这些放在了一个工具类里,代码如下:
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
/**
* 定时任务工具类
* @author linhai
*
*/
public class QuartsUtils {
public final static String EACH_MINITE = "0 * * * * ?"; //每分钟执行
public final static String EACH_HOUR = "0 0 * * * ?"; //每小时执行
public final static String EACH_DAY = "0 0 0 * * ?"; //每天执行
private static Scheduler sched;
static{
try{
try {
sched = new StdSchedulerFactory().getScheduler();
} catch (org.quartz.SchedulerException e) {
throw new SchedulerException(e.getMessage(), e);
}
}
catch(Exception e ){
e.printStackTrace();
}
}
/**
* 启动定时任务
* @param jobid 任务id
* @param cron 定时表达式,采用cron表达式
* @param classpath 执行类路径
* @param jobdata 自定义参数
* @return
*/
public static boolean startCronWork(String jobid, String cron, String classpath, Object jobdata) {
boolean b= false;
try {
JobKey jk=JobKey.jobKey(jobid, "common");
if(QuartsUtils.sched.checkExists(jk)){
sched.pauseJob(jk);
sched.deleteJob(jk);
}
b = register(jobid, cron, classpath, jobdata);
System.out.println("启动定时任务" + jobid + "成功!");
return b;
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
/**
* 停止定时任务
* @param id 任务id
* @return
*/
public static boolean shutdownWork(String id) {
try {
JobKey jk=JobKey.jobKey(id, "common");
if(sched.checkExists(jk)){
sched.pauseJob(jk);
sched.deleteJob(jk);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 任务注册
* @param jobid 任务id
* @param cron 定时表达式,采用cron表达式
* @param classpath 执行类路径
* @param jobdata 自定义参数
* @return
*/
private static boolean register(String id, String cron, String classpath, Object jobdata) {
JobDetail job = JobBuilder.newJob(QuartsJobExecutor.class)
.withIdentity(id, "common")
.build();
Map<String, Object> map = new HashMap<String, Object>();
map.put("data", jobdata);
map.put("classpath", classpath);
job.getJobDataMap().put("data", map);
if (!("".equals(cron) && (null == cron))) {
Trigger trigger = null;
try {
trigger = TriggerBuilder.newTrigger()
.withIdentity(id, "common")
.withSchedule(CronScheduleBuilder.cronSchedule(new CronExpression(cron)))
//.forJob("myJob", "group1")
.build();
sched.start();
sched.scheduleJob(job,trigger);
return true;
} catch (ParseException | SchedulerException e) {
e.printStackTrace();
return false;
}
} else {
return false;
}
}
}
通过调用QuartsUtils.startCronWork(jobid, cron, clathpath, data);去启动定时器。其中,jobid表示任务ID,可以用具体业务的某个不重复的字符串来作为任务ID。
cron表示的是时间格式,需要满足成以下格式,定义的一个字符串:
// 根据判断,判断是分、时还是天
String cron = "";
String num = data.get("acquisition_rate").toString();
if("1".equals(data.get("unit"))){ // 时
cron = "0 0 */"+num+" * * ?";
}else if("2".equals(data.get("unit"))){ // 分
cron = "0 */"+num+" * * * ? *";
}else if("3".equals(data.get("unit"))){ // 天
cron = "0 0 0 */"+num+" * ?";
}
clathpath 表示的是实现类的全路径,就是以上步骤的第二步实现的那个类的全路径。
data表示的是需要传递的参数,是一个Map参数。
一个用quartz实现的定时任务就这样完成了。同时,需要的jar包是quartz-2.2.2.jar,可自己网上去下载。也可以点击链接直接去下载。