1. 程式人生 > >Java中關於定時自動任務的實現

Java中關於定時自動任務的實現

先說明一下,Java有自帶的定時任務類Timer和TimerTask,可以實現簡單的定時任務,但是對於複雜的任務處理支援的不是很好。這裡就不做說明了,直接上今天所使用的第三方的定時自動任務的框架quartz,jar的版本是2.0.2;

注:如果是不需要動態設定時間的,可以直接和spring結合,通過配置檔案的方式更簡單。我們文中主要是對動態設定時間的定時自動任務做一下說明。

說一下,定時自動任務的三個要素:

1:自動任務的控制器,用於操作定時自動任務的的管理器;

2:定時自動任務的觸發器,觸發定時自動任務;

3:執行自動任務的job類了;

這裡是定時任務管理類的程式碼:

 public class SchedulerRun {

private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

/**
* 功能: 新增一個定時任務
* @param jobName 任務名
* @param jobGroupName 任務組名
* @param triggerName 觸發器名
* @param triggerGroupName 觸發器組名
* @param jobClass 任務的類型別 eg:TimedMassJob.class
* @param cron 時間設定 表示式,參考quartz說明文件
* @param objects 可變引數需要進行傳參的值
*/
public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String cron,Object...objects) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
// 任務名,任務組,任務執行類
JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
// 觸發器
if(objects!=null){
for (int i = 0; i < objects.length; i++) {
//該資料可以通過Job中的JobDataMap dataMap = context.getJobDetail().getJobDataMap();來進行引數傳遞值
jobDetail.getJobDataMap().put("data"+(i+1), objects[i]);
}
}
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 觸發器名,觸發器組
triggerBuilder.withIdentity(triggerName,triggerGroupName);
triggerBuilder.startNow();
// 觸發器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 建立Trigger物件
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 排程容器設定JobDetail和Trigger
scheduler.scheduleJob(jobDetail, trigger);
// 啟動
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
* 功能:修改一個任務的觸發時間
* @param jobName
* @param jobGroupName
* @param triggerName 觸發器名
* @param triggerGroupName 觸發器組名
* @param cron 時間設定,參考quartz說明文件
*/
public static void modifyJobTime(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String cron) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
// 觸發器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 觸發器名,觸發器組
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 觸發器時間設定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 建立Trigger物件
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一個任務的觸發時間
scheduler.rescheduleJob(triggerKey, trigger);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
* 功能: 移除一個任務
* @param jobName
* @param jobGroupName
* @param triggerName
* @param triggerGroupName
*/
public static void removeJob(String jobName, String jobGroupName,String triggerName, String triggerGroupName) {
try {
Scheduler scheduler = schedulerFactory.getScheduler();

TriggerKey triggerKey = TriggerKey.triggerKey(triggerName,triggerGroupName);
// 停止觸發器
scheduler.pauseTrigger(triggerKey);
// 移除觸發器
scheduler.unscheduleJob(triggerKey);
// 刪除任務
scheduler.deleteJob(JobKey.jobKey(jobName,jobGroupName));
} catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
*
* 功能:啟動所有定時任務
*/
public static void startJobs() {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 功能:關閉所有定時任務
*/
public static void shutdownJobs() {
try {
Scheduler scheduler = schedulerFactory.getScheduler();
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

下面是在任務棧中新增一個自動任務

 HtzckcJob job = new HtzckcJob();  

SchedulerRun.addJob(job_name,jobGroupName,triggerName,triggerGroupName,job.getClass(),cronDateStr,null);

上面的引數cronDateStr是通過時間類轉換得到的cron的表示式:

轉換實現如下:

public class FormatDateToCron {
/*** 
     *  功能描述:日期轉換cron表示式
     * @param date 
     * @param dateFormat : e.g:yyyy-MM-dd HH:mm:ss 
     * @return 
     */  
    public static String formatDateByPattern(Date date,String dateFormat){  
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);  
        String formatTimeStr = null;  
        if (date != null) {  
            formatTimeStr = sdf.format(date);  
        }  
        return formatTimeStr;  
    }
    
    /**
     * 功能描述:每天ss mm HH這個時間執行執行一次
     * @param date
     * @return
     */
    public static String getCronDay(Date  date){  
        String dateFormat="ss mm HH * * ?";  
        return formatDateByPattern(date, dateFormat);  
    }
    
    /**
     * 功能描述:每天ss mm HH這個時間執行執行一次
     * @param date
     * @return
     */
    public static String getCronMonth(Date  date){  
        String dateFormat="ss mm HH dd MM ?";  
        return formatDateByPattern(date, dateFormat);  
    }  
    
    /**
     * 功能描述:每天ss mm HH這個時間執行執行一次
     * @param date
     * @return
     */
    public static String getCronSecond(Date  date){  
        String dateFormat="ss * * * * ?";  
        return formatDateByPattern(date, dateFormat);  
    }  
}

自動任務執行的job,這裡書寫業務方法,

public class HtzckcJob implements Job{


@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
//1: 執行時間
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
System.out.println(sdf.format(new Date()));
}


}

主要的程式碼都有註釋,底層的技術可以自行檢視文件,大家有更好的方式可以一起交流一下!