Java定時任務工具Quartz——學習筆記(一)
阿新 • • 發佈:2019-02-17
最近在準備做一個生日提醒的Demo,於是有了這篇部落格。咳咳,雖然可以在手機日曆設定提醒,但是我們要有自力更生的覺悟以及能力,自己能做當然用自己的嘛。
一、初步瞭解
百度百科是這樣介紹Quartz這個專案的。
Quartz可以用來建立簡單或為執行十個,百個,甚至是好幾萬個Jobs這樣複雜的程式。
雖然我們可以使用Java的Timer以及執行緒來實現,但是卻不太方便的精確的定位到某年某日某時某分某秒。所以對於這樣的需求,使用Quartz是最好的選擇
二、引入jar包
網上部分部落格說
要使用Quartz,必須要引入以下這幾個包:
1、log4j-1.2.16 2、quartz-2.1.7 3、slf4j-api-1.6.1.jar 4、slf4j-log4j12-1.6.1.jar
這些jar包都在Quartz的包內包含,不過似乎都引入會出現一些衝突,我使用的是2.2.3的jar包,當我引入quartz和log4j的jar,時候發生了衝突。最後引入的jar包如下:
注意,我的專案是Java專案,不是J2EE。
三、新增要被執行的任務類
這個類的execute()方法會在觸發器被觸發的時候執行,即到了預設時間時會被執行。
package Toolkit;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
System.out.println("現在時間是:" + simpleDateFormat.format(new Date()));
System.out.println("JobExecutionContext內容是:" + jobExecutionContext.getJobDetail());
}
}
四、建立、執行任務排程
話不多說,都在程式碼裡~
import Toolkit.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
public class Main {
public void start(){
//第一步,必需要取得一個排程器
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
try {
//任務排程器
Scheduler scheduler = schedulerFactory.getScheduler();
//第二步,獲取JobDetail物件,來描述Job的實現類及其它相關的靜態資訊,如Job名字、描述、關聯監聽器等資訊
JobDetail job = newJob(MyJob.class).withIdentity("job1", "group1").build();
//複雜的Trigger
//job1將 從0秒開始 每隔20秒執行一次
//第三步,獲取trigger
CronTrigger trigger1 = newTrigger()
.withIdentity("trigger1","group1")
.withSchedule(cronSchedule("0/20 * * * * ?"))
.build();
//第四步,將trigger和job繫結,一個Job可以對應多個Trigger,但一個Trigger只能對應一個Job。
Date date = scheduler.scheduleJob(job,trigger1);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(job.getKey() + "已經被安排執行於:" + simpleDateFormat.format(date) + ",並且以如下重複規則重複執行" + trigger1.getCronExpression() + ",trigger為:" + trigger1.getKey().getName());
// 開始執行,start()方法被呼叫後,計時器就開始工作
scheduler.start();
try {
//主執行緒等待十分鐘
Thread.sleep(60L * 10000L);
} catch (Exception e) { }
//關閉定時排程,定時器不再工作
scheduler.shutdown(true);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public static void main(String args[]){
Main main = new Main();
main.start();
}
}
其中有兩點需要詳細說一說:
1.0/20 * * * * ?
,有關萬用字元的含義請戳這裡!
2.一個Job可以繫結多個Trigger,一個Trigger只能繫結在一個Job上。
話不多說,都在程式碼裡。下面給出一個Job繫結多個Trigger的Demo。
import Toolkit.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
public class Main {
public void start(){
//第一步,必需要取得一個排程器
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
try {
//任務排程器
Scheduler scheduler = schedulerFactory.getScheduler();
//第二步,獲取JobDetail物件,來描述Job的實現類及其它相關的靜態資訊,如Job名字、描述、關聯監聽器等資訊
JobDetail job = newJob(MyJob.class).withIdentity("job1", "group1").build();
//複雜的Trigger
//job1將 從0秒開始 每隔20秒執行一次
//第三步,獲取trigger
CronTrigger trigger1 = newTrigger()
.withIdentity("trigger1","group1")
.withSchedule(cronSchedule("0 35 20 4 9 ?"))
.build();
//注意這裡,多個Trigger繫結到一個Job上
CronTrigger trigger2 = newTrigger()
.withIdentity("trigger2","group1")
.forJob("job1","group1")
.withSchedule(cronSchedule("0/5 * * * * ?"))
.build();
//第四步,將trigger和job繫結,一個Job可以對應多個Trigger,但一個Trigger只能對應一個Job。
Date date = scheduler.scheduleJob(job,trigger1);
//注意這裡,多個Trigger繫結到一個Job上
Date date1 = scheduler.scheduleJob(trigger2);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(job.getKey() + "已經被安排執行於:" + simpleDateFormat.format(date) + ",並且以如下重複規則重複執行" + trigger1.getCronExpression() + ",trigger為:" + trigger1.getKey().getName());
System.err.println(job.getKey() + "已經被安排執行於:" + simpleDateFormat.format(date1) + ",並且以如下重複規則重複執行" + trigger2.getCronExpression() + ",trigger為:" + trigger2.getKey().getName());
// 開始執行,start()方法被呼叫後,計時器就開始工作,計時排程中允許放入多個Job
scheduler.start();
try {
//主執行緒等待十分鐘
Thread.sleep(60L * 10000L);
} catch (Exception e) { }
//關閉定時排程,定時器不再工作
scheduler.shutdown(true);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public static void main(String args[]){
Main main = new Main();
main.start();
}
}
CronTrigger配置格式:
格式: [秒] [分] [小時] [日] [月] [周] [年]
序號 | 說明 | 是否必填 | 允許填寫的值 | 允許的萬用字元 |
---|---|---|---|---|
1 | 秒 | 是 | 0-59 | , - * / |
2 | 分 | 是 | 0-59 | , - * / |
3 | 小時 | 是 | 0-23 | , - * / |
4 | 日 | 是 | 1-31 | , - * ? / L W |
5 | 月 | 是 | 1-12 or JAN-DEC | , - * / |
6 | 周 | 是 | 1-7 or SUN-SAT | , - * ? / L # |
7 | 年 | 否 | empty 或 1970-2099 | , - * / |
事例:
CronTrigger配置內容 | 含義 |
---|---|
0 0 12 * * ? | 每天12點觸發 |
0 15 10 ? * * | 每天10點15分觸發 |
0 15 10 * * ? | 每天10點15分觸發 |
0 15 10 * * ? * | 每天10點15分觸發 |
0 15 10 * * ? 2005 | 2005年每天10點15分觸發 |
0 * 14 * * ? | 每天下午的 2點到2點59分每分觸發 |
0 0/5 14 * * ? | 每天下午的 2點到2點59分(整點開始,每隔5分觸發) |
0 0/5 14,18 * * ? | 每天下午的 2點到2點59分(整點開始,每隔5分觸發) 每天下午的 18點到18點59分(整點開始,每隔5分觸發) |
0 0-5 14 * * ? | 每天下午的 2點到2點05分每分觸發 |
0 10,44 14 ? 3 WED | 3月分每週三下午的 2點10分和2點44分觸發 |
0 15 10 ? * MON-FRI | 從週一到週五每天上午的10點15分觸發 |
0 15 10 15 * ? | 每月15號上午10點15分觸發 |
0 15 10 L * ? | 每月最後一天的10點15分觸發 |
0 15 10 ? * 6L | 每月最後一週的星期五的10點15分觸發 |
0 15 10 ? * 6L 2002-2005 | 從2002年到2005年每月最後一週的星期五的10點15分觸發 |
0 15 10 ? * 6#3 | 每月的第三週的星期五開始觸發 |
0 0 12 1/5 * ? | 每月的第一個中午開始每隔5天觸發一次 |
0 11 11 11 11 ? | 每年的11月11號 11點11分觸發(光棍節) |