corn表達(dá)式是:由若干數(shù)字、空格、符號按一定的規(guī)則,組成的一組字符串,從而表達(dá)時間的信息。
好像和正則表達(dá)式有點(diǎn)類似哈,都是一個字符串表示一些信息。
Cron 表達(dá)式生成器: Smart Tools - 智能工具箱
簡介
Cron 表達(dá)式是一個具有時間含義的字符串,字符串以 5 或 6 個空格隔開,分為 6 或 7 個域,每一個域代表一種含義。 Cron 有如下兩種語法格式:
-
秒 分 小時 日期 月份 星期
-
秒 分 小時 日期 月份 星期 年
即:秒 分 小時 日期 月份 星期 年(可為空)
主流工具
目前的 Cron 表達(dá)式主要有兩類,分別是:
-
Linux crontab 命令 (Crontab 是linux系統(tǒng)自帶的定時任務(wù),用于設(shè)置周期性執(zhí)行的本地腳本。Crontab的cron表達(dá)式只能精確到分鐘。例如,* * * * ?)
-
Java Quartz(Quartz 是一個完全由 Java 編寫的開源作業(yè)調(diào)度框架,為 Java 應(yīng)用進(jìn)行任務(wù)調(diào)度提供了簡單卻強(qiáng)大的機(jī)制。Quartz的cron表達(dá)式可以精確到秒。例如,* * * * * ?)
其中,Linux crontab 僅支持分鐘級別的任務(wù)調(diào)度;Java Quartz 則可以秒級別的任務(wù)調(diào)度;
Linux crontab 中的 cron 語法規(guī)范
* * * * *
- - - - -
| | | | |
| | | | +----- 星期中星期幾 (0 - 6) (星期天為0)
| | | +---------- 月份 (1 - 12)
| | +--------------- 一個月中的第幾天 (1 - 31)
| +-------------------- 小時 (0 - 23)
+------------------------- 分鐘 (0 - 59)
Java Quartz 中的 cron 語法規(guī)范
* * * * * *
- - - - - -
| | | | | |
| | | | | +----- 星期中星期幾 (0 - 6) (星期天為0)
| | | | +---------- 月份 (1 - 12)
| | | +--------------- 一個月中的第幾天 (1 - 31)
| | +-------------------- 小時 (0 - 23)
| +------------------------- 分鐘 (0 - 59)
+------------------------------ 秒 (0 - 60)
域取值
下表為 Cron 表達(dá)式中每個域能夠取的值以及支持的特殊字符。
域 |
是否必需 |
取值范圍 |
特殊字符 |
秒 |
是 |
[0, 59] |
* , - / |
分鐘 |
是 |
[0, 59] |
* , - / |
小時 |
是 |
[0, 23] |
* , - / |
日期 |
是 |
[1, 31] |
* , - / ? L W C |
月份 |
是 |
[1, 12] |
* , - / |
星期 |
是 |
[1, 7] 其中 1 表示星期一,7 表示星期日。 |
* , - / ? L C # |
年 |
否 |
留空,1970~2099 |
, - * / |
特殊字符
Cron 表達(dá)式中的每個域都支持一定數(shù)量的特殊字符,每個特殊字符有其特殊含義。
特殊字符 |
含義 |
示例 |
* |
所有可能的值 |
在月份域中,* 表示每個月;在星期域中,* 表示星期的每一天。 |
, |
列出枚舉值 |
在分鐘域中,5,20 表示分別在 5 分鐘和 20 分鐘觸發(fā)一次。 |
- |
范圍 |
在分鐘域中,5-20 表示從 5 分鐘到 20 分鐘之間每隔一分鐘觸發(fā)一次。 |
/ |
表示起始時間開始觸發(fā),然后每隔固定時間觸發(fā)一次 |
在分鐘域中,0/15 表示從第 0 分鐘開始,每 15 分鐘觸發(fā)一次。在分鐘域中3/20表示從第 3 分鐘開始,每 20 分鐘觸發(fā)一次。 |
? |
不指定值,僅日期和星期域支持該字符 |
當(dāng)日期或星期域其中之一被指定了值以后,為了避免沖突,需要將另一個域的值設(shè)為?。 |
L |
單詞 Last 的首字母,表示最后一天,僅日期和星期域支持該字符 |
在日期域中,L 表示某個月的最后一天。在星期域中,L 表示一個星期的最后一天,也就是星期日(SUN)。如果在 L 前有具體的內(nèi)容,例如,在星期域中的 6L,表示這個月的最后一個星期六。 |
W |
表示有效工作日(周一到周五),只能出現(xiàn)在日期域,系統(tǒng)將在離指定日期最近的有效工作日觸發(fā)事件。W 字符尋找當(dāng)前月份中最近有效工作日,連用字符 LW 時表示為指定月份的最后一個工作日。 |
在日期域中使用 5W, 如果 5 號是星期六,則將在最近的工作日星期五,即 4 日觸發(fā)。如果 5 日是星期天,則將在最近的工作日星期一,即 6 日觸發(fā);如果 5 日在星期一到星期五中的一天,則就在 5 日觸發(fā)。 |
# |
確定每個月第幾個星期幾,僅星期域支持該字符。 |
在星期域中,4#2表示某月的第二個星期四。 |
C |
這個字符依靠一個指定的“日歷”。也就是說這個表達(dá)式的值依賴于相關(guān)的“日歷”的計算結(jié)果,如果沒有“日歷”關(guān)聯(lián),則等價于所有包含的“日歷”。僅日期和星期域支持該字符。 |
日期域是“5C”表示關(guān)聯(lián)“日歷”中第一天,或者這個月開始的第一天的后5天。星期域是“1C”表示關(guān)聯(lián)“日歷”中第一天,或者星期的第一天的后1天,也就是周日的后一天(周一)。 |
秒
允許值范圍: 0~59 ,不允許為空值,若值不合法,調(diào)度器將拋出SchedulerException異常
"*" 代表每隔1秒鐘觸發(fā)
"," 代表在指定的秒數(shù)觸發(fā),比如"0,15,45"代表0秒、15秒和45秒時觸發(fā)任務(wù)
"-" 代表在指定的范圍內(nèi)觸發(fā),比如"25-45"代表從25秒開始觸發(fā)到45秒結(jié)束觸發(fā),每隔1秒觸發(fā)1次
"/" 代表觸發(fā)步進(jìn)(step),"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/20"或者"*/20"代表從0秒鐘開始,每隔20秒鐘觸發(fā)1次,即0秒觸發(fā)1次,20秒觸發(fā)1次,40秒觸發(fā)1次;"5/20"代表5秒觸發(fā)1次,25秒觸發(fā)1次,45秒觸發(fā)1次;"10-45/20"代表在[10,45]內(nèi)步進(jìn)20秒命中的時間點(diǎn)觸發(fā),即10秒觸發(fā)1次,30秒觸發(fā)1次
分鐘
允許值范圍: 0~59 ,不允許為空值,若值不合法,調(diào)度器將拋出SchedulerException異常
"*" 代表每隔1分鐘觸發(fā)
"," 代表在指定的分鐘觸發(fā),比如"10,20,40"代表10分鐘、20分鐘和40分鐘時觸發(fā)任務(wù)
"-" 代表在指定的范圍內(nèi)觸發(fā),比如"5-30"代表從5分鐘開始觸發(fā)到30分鐘結(jié)束觸 發(fā),每隔1分鐘觸發(fā)
"/" 代表觸發(fā)步進(jìn)(step),"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/25"或者"*/25"代表從0分鐘開始,每隔25分鐘觸發(fā)1次,即0分鐘觸發(fā)1次,第25分鐘觸發(fā)1次,第50分鐘觸發(fā)1次;"5/25"代表5分鐘觸發(fā)1次,30分鐘觸發(fā)1次,55分鐘觸發(fā)1次;"10-45/20"代表在[10,45]內(nèi)步進(jìn)20分鐘命中的時間點(diǎn)觸發(fā),即10分鐘觸發(fā)1次,30分鐘觸發(fā)1次
小時
允許值范圍: 0~23 ,不允許為空值,若值不合法,調(diào)度器將拋出SchedulerException異常
"*" 代表每隔1小時觸發(fā)
"," 代表在指定的時間點(diǎn)觸發(fā),比如"10,20,23"代表10點(diǎn)鐘、20點(diǎn)鐘和23點(diǎn)觸發(fā)任務(wù)
"-" 代表在指定的時間段內(nèi)觸發(fā),比如"20-23"代表從20點(diǎn)開始觸發(fā)到23點(diǎn)結(jié)束觸發(fā),每隔1小時觸發(fā)
"/" 代表觸發(fā)步進(jìn)(step),"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/1"或者"*/1"代表從0點(diǎn)開始觸發(fā),每隔1小時觸發(fā)1次;"1/2"代表從1點(diǎn)開始觸發(fā),以后每隔2小時觸發(fā)一次
日期
允許值范圍: 1~12 (JAN-DEC),不允許為空值,若值不合法,調(diào)度器將拋出SchedulerException異常
"*" 代表每個月都觸發(fā)
"," 代表在指定的月份觸發(fā),比如"1,6,12"代表1月份、6月份和12月份觸發(fā)任務(wù)
"-" 代表在指定的月份范圍內(nèi)觸發(fā),比如"1-6"代表從1月份開始觸發(fā)到6月份結(jié)束觸發(fā),每隔1個月觸發(fā)
"/" 代表觸發(fā)步進(jìn)(step),"/"前面的值代表初始值("*"等同"1"),后面的值代表偏移量,比如"1/2"或者"*/2"代表從1月份開始觸發(fā),每隔2個月觸發(fā)1次;"6/6"代表從6月份開始觸發(fā),以后每隔6個月觸發(fā)一次;"1-6/12"表達(dá)式意味著每年1月份觸發(fā)
"C" 這個字符依靠一個指定的“日歷”。也就是說這個表達(dá)式的值依賴于相關(guān)的“日歷”的計算結(jié)果,如果沒有“日歷”關(guān)聯(lián),則等價于所有包含的“日歷”。比如“5C”表示關(guān)聯(lián)“日歷”中第一天,或者這個月開始的第一天的后5天。
星期
允許值范圍: 1~7 (SUN-SAT),1代表星期天(一星期的第一天),以此類推,7代表星期六(一星期的最后一天),不允許為空值,若值不合法,調(diào)度器將拋出SchedulerException異常
"*" 代表每星期都觸發(fā);
"?" 與{日期}互斥,即意味著若明確指定{日期}觸發(fā),則表示{星期}無意義,以免引起沖突和混亂
"," 代表在指定的星期約定觸發(fā),比如"1,3,5"代表星期天、星期二和星期四觸發(fā)
"-" 代表在指定的星期范圍內(nèi)觸發(fā),比如"2-4"代表從星期一開始觸發(fā)到星期三結(jié)束觸發(fā),每隔1天觸發(fā)
"/" 代表觸發(fā)步進(jìn)(step),"/"前面的值代表初始值("*"等同"1"),后面的值代表偏移量,比如"1/3"或者"*/3"代表從星期天開始觸發(fā),每隔3天觸發(fā)1次;"1-5/2"表達(dá)式意味著在[1,5]范圍內(nèi),每隔2天觸發(fā),即星期天、星期二、星期四觸發(fā)
"L" 如果{星期}占位符如果是"L",即意味著星期的的最后一天觸發(fā),即星期六觸發(fā),L= 7或者 L = SAT,因此,"5L"意味著一個月的最后一個星期四觸發(fā)
"#" 用來指定具體的周數(shù),"#"前面代表星期,"#"后面代表本月第幾周,比如"2#2"表示本月第二周的星期一,"5#3"表示本月第三周的星期四,因此,"5L"這種形式只不過是"#"的特殊形式而已
"C" 這個字符依靠一個指定的“日歷”。也就是說這個表達(dá)式的值依賴于相關(guān)的“日歷”的計算結(jié)果,如果沒有“日歷”關(guān)聯(lián),則等價于所有包含的“日歷”。比如:“1C”表示關(guān)聯(lián)“日歷”中第一天,或者星期的第一天的后1天,也就是周日的后一天(周一)。
年份
允許值范圍: 1970~2099 ,允許為空,若值不合法,調(diào)度器將拋出SchedulerException異常
"*"代表每年都觸發(fā)
","代表在指定的年份才觸發(fā),比如"2011,2012,2013"代表2011年、2012年和2013年觸發(fā)任務(wù)
"-"代表在指定的年份范圍內(nèi)觸發(fā),比如"2011-2020"代表從2011年開始觸發(fā)到2020年結(jié)束觸發(fā),每隔1年觸發(fā)
"/"代表觸發(fā)步進(jìn)(step),"/"前面的值代表初始值("*"等同"1970"),后面的值代表偏移量,比如"2011/2"或者"*/2"代表從2011年開始觸發(fā),每隔2年觸發(fā)1次
注意:除了{(lán)日期}和{星期}可以使用"?"來實現(xiàn)互斥,表達(dá)無意義的信息之外,其他占位符都要具有具體的時間含義,且依賴關(guān)系為:年->月->日期(星期)->小時->分鐘->秒數(shù)
Cron 表達(dá)式示例
示例 1 |
說明 |
0 15 10 ? * * |
每天上午 10:15 執(zhí)行任務(wù) |
0 15 10 * * ? |
每天上午 10:15 執(zhí)行任務(wù) |
0 0 12 * * ? |
每天中午 12:00 執(zhí)行任務(wù) |
0 0 10,14,16 * * ? |
每天上午 10:00 點(diǎn)、下午 14:00 以及下午 16:00 執(zhí)行任務(wù) |
0 0/30 9-17 * * ? |
每天上午 09:00 到下午 17:00 時間段內(nèi)每隔半小時執(zhí)行任務(wù) |
0 * 14 * * ? |
每天下午 14:00 到下午 14:59 時間段內(nèi)每隔 1 分鐘執(zhí)行任務(wù) |
0 0-5 14 * * ? |
每天下午 14:00 到下午 14:05 時間段內(nèi)每隔 1 分鐘執(zhí)行任務(wù) |
0 0/5 14 * * ? |
每天下午 14:00 到下午 14:55 時間段內(nèi)每隔 5 分鐘執(zhí)行任務(wù) |
0 0/5 14,18 * * ? |
每天下午 14:00 到下午 14:55、下午 18:00 到下午 18:55 時間段內(nèi)每隔 5 分鐘執(zhí)行任務(wù) |
0 0 12 ? * WED |
每個星期三中午 12:00 執(zhí)行任務(wù) |
0 15 10 15 * ? |
每月 15 日上午 10:15 執(zhí)行任務(wù) |
0 15 10 L * ? |
每月最后一日上午 10:15 執(zhí)行任務(wù) |
0 15 10 ? * 6L |
每月最后一個星期六上午 10:15 執(zhí)行任務(wù) |
0 15 10 ? * 6#3 |
每月第三個星期六上午 10:15 執(zhí)行任務(wù) |
0 10,44 14 ? 3 WED |
每年 3 月的每個星期三下午 14:10 和 14:44 執(zhí)行任務(wù) |
cron 表達(dá)式用途
cron 表達(dá)式最主要的就是在程序中做一些定時任務(wù),比如某些系統(tǒng)的報表數(shù)據(jù),某些游戲的排行榜,由于這些數(shù)據(jù)量實時統(tǒng)計非常消耗程序性能,所以就每隔一段時間,通過自動任務(wù)跑一次,這樣可以極大的提升用戶瀏覽體驗,要是在游戲里,還可以增加一種神秘感。
另外,某些具體點(diǎn)的數(shù)據(jù)拉取,比如你如果從事平臺對接工作,要從某些平臺下載你的訂單,那么肯定是每隔多久抓一次。
又比如你寫個爬蟲,要實時的了解你的某些數(shù)據(jù),然后從這些數(shù)據(jù)中反應(yīng)你的情況。
一個簡單的java項目示例
導(dǎo)入依賴
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>

定義Job
定義一個HelloJob類實現(xiàn)Job接口
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("Say hello to Quartz {" + new Date() +"}");
}
}

測試
寫個主函數(shù),在主函數(shù)里面完成整個Quartz的操作過程
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Date;
public class HelloQuartz {
public static void main(String[] args) throws SchedulerException {
//1.創(chuàng)建Scheduler的工廠
SchedulerFactory sf = new StdSchedulerFactory();
//2.從工廠中獲取調(diào)度器實例
Scheduler scheduler = sf.getScheduler();
//3.創(chuàng)建JobDetail
JobDetail jb = JobBuilder.newJob(HelloJob.class)
.withDescription("this is a job") //job的描述
.withIdentity("Job", "Group") //job 的name和group
.build();
//任務(wù)運(yùn)行的時間,SimpleSchedle類型觸發(fā)器有效
long time= System.currentTimeMillis() + 3*1000L; //3秒后啟動任務(wù)
Date statTime = new Date(time);
//4.創(chuàng)建Trigger
//使用SimpleScheduleBuilder或者CronScheduleBuilder
Trigger t = TriggerBuilder.newTrigger()
.withDescription("")
.withIdentity("Trigger", "TriggerGroup")
//.withSchedule(SimpleScheduleBuilder.simpleSchedule())
.startAt(statTime) //默認(rèn)當(dāng)前時間啟動
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")) // 10秒執(zhí)行一次
.build();
//5.注冊任務(wù)和定時器
scheduler.scheduleJob(jb, t);
//6.啟動 調(diào)度器
scheduler.start();
}
}

運(yùn)行截圖:

一個簡單的sprin boot項目示例
導(dǎo)入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
? ? </dependency>

定義Job
定義一個HelloJob類實現(xiàn)Job接口
package com.example.demo;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("Say hello to Quartz {" + new Date() +"}");
}
}

測試
寫個主函數(shù),在主函數(shù)里面完成整個Quartz的操作過程
package com.example.demo;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 要配置Quartz的調(diào)度器Scheduler
// 調(diào)度器由SpringBoot管理,所以就變成了配置Spring
@Configuration
public class Demo {
// 配置的核心是向Spring容器保存一個job和保存一個Trigger
// 創(chuàng)建一個封裝Job對象的類型JobDetail
// 使用@Bean注解標(biāo)記的方法將這個對象保存到Spring容器
@Bean
public JobDetail addStock(){
//newJob方法就是在綁定要運(yùn)行的Job接口實現(xiàn)類,需要實現(xiàn)類的反射做參數(shù)
return JobBuilder.newJob(HelloJob.class)
// 給當(dāng)前JobDetail對象在調(diào)度環(huán)境中起名
.withIdentity("addStock")
// 即使沒有觸發(fā)器綁定當(dāng)前JobDetail對象,也不會被刪除
.storeDurably()
.build();
}
// 下面是觸發(fā)器的聲明,也會保存到Spring容器中
// 它能夠設(shè)置job的運(yùn)行時機(jī)
@Bean
public Trigger addStockTrigger(){
System.out.println("Trigger保存到Spring容器中");
// 定義Cron表達(dá)式
CronScheduleBuilder cron=
CronScheduleBuilder.cronSchedule("0/10 * * * * ?"); // 10秒執(zhí)行一次
return TriggerBuilder.newTrigger()
// 綁定要運(yùn)行的JobDetail對象
.forJob(addStock())
// 為觸發(fā)器起名
.withIdentity("addStockTrigger")
// 綁定cron表達(dá)式
.withSchedule(cron)
.build();
}
}

運(yùn)行截圖:

驗證cron表達(dá)式有效性的示例
導(dǎo)入依賴
???????
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
代碼
校驗cron表達(dá)式只用一個方法就可以了,在主函數(shù)中進(jìn)行測試。
import org.quartz.CronExpression;
import java.text.ParseException;
public class Demo {
public static void main(String[] args) {
System.out.println(getInvalidMessage("0/5 * * * * ? *")); // cron表達(dá)式有效
System.out.println(getInvalidMessage("11 0/5 * * * * ? *")); // cron表達(dá)式無效
}
/**
* 驗證一個cron表達(dá)式是否有效:返回一個字符串值,表示該無效Cron表達(dá)式給出的提示信息
*
* @param cronExpression Cron表達(dá)式
* @return String 無效時返回表達(dá)式錯誤描述,如果有效返回null
*/
public static String getInvalidMessage(String cronExpression) {
try {
new CronExpression(cronExpression);
return null;
} catch (ParseException pa) {
return pa.getMessage();
}
}
}
運(yùn)行截圖:
Linux的crontab命令
在Linux中的cron表達(dá)式與上文所述有所不同,更準(zhǔn)確地說是更加精簡了。
crontab的命令構(gòu)成為 cron表示式 + command,這里的cron表達(dá)
Minutes Hours DayOfMonth Month DayOfWeek
而操作符則有:
* / - ,
一起來看看幾個例子:
1. 每晚的21:30重啟smb
30 21 * * * /etc/init.d/smb restart
2. 每星期六的晚上11:00 pm重啟smb
0 23 * * 6 /etc/init.d/smb restart文章來源:http://www.zghlxwxcb.cn/news/detail-761906.html
3. 晚上11點(diǎn)到早上7點(diǎn)之間,每隔一小時重啟smb
0 23-7/1 * * * /etc/init.d/smb restart文章來源地址http://www.zghlxwxcb.cn/news/detail-761906.html
到了這里,關(guān)于cron表達(dá)式 詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!