Quartz 定時(shí)任務(wù)框架詳解

1.Quartz 體系結(jié)構(gòu)

Quartz 設(shè)計(jì)有四個(gè)核心類右锨,分別是Scheduler(調(diào)度器)瞧筛、Job(任務(wù)) 、Trigger(觸發(fā)器)抹估、JobDetail(任務(wù)詳情),他們是使用Quartz的關(guān)鍵弄兜。


1.1 Job

Job:定義需要執(zhí)行的任務(wù)药蜻,該類是一個(gè)接口瓷式,只定義了一個(gè)方法execute(JobExecutionContext context),在實(shí)現(xiàn)類的execute方法中編寫所需要定時(shí)執(zhí)行的Job(任務(wù)),JobExcutionContext類提供了調(diào)度應(yīng)用的一些信息语泽。Job運(yùn)行時(shí)的信息保存在JobDataMap實(shí)例中贸典。

1.2 Trigger

Trigger:負(fù)責(zé)設(shè)置調(diào)度策略。該類是一個(gè)接口踱卵,描述觸發(fā)job執(zhí)行的時(shí)間觸發(fā)規(guī)則廊驼。主要有SimpleTrigger和CronTrigger這兩個(gè)子類。當(dāng)且僅當(dāng)需調(diào)度一次或者以固定時(shí)間間隔周期執(zhí)行調(diào)度惋砂,SimpleTrigger 是最適合的選擇妒挎;而CronTrigger則可以通過Cron表達(dá)式定義出各種復(fù)雜時(shí)間規(guī)則的調(diào)度方案:如在周一到周五的15:00 ~ 16:00 執(zhí)行調(diào)度等。

1.3 Scheduler

Scheduler:調(diào)度器就相當(dāng)于一個(gè)容器西饵,裝載著任務(wù)和觸發(fā)器酝掩。該類是一個(gè)接口。代表一個(gè)Quartz的獨(dú)立運(yùn)行容器眷柔。Trigger和JobDetail可以注冊(cè)到Scheduler中期虾,兩者在Scheduler中擁有各自的組及名稱,組及名稱是Scheduler查找定位容器中某一對(duì)象的依據(jù)驯嘱。

1.4 JobDetail

JobDetail:描述Job的實(shí)現(xiàn)類及其它相關(guān)的靜態(tài)信息镶苞,如:Job名字、描述鞠评、關(guān)聯(lián)監(jiān)聽器等信息宾尚。Quartz每次調(diào)度Job時(shí),都重新創(chuàng)建一個(gè)Job實(shí)例谢澈,它接受一個(gè)Job實(shí)現(xiàn)類煌贴,以便運(yùn)行時(shí)通過newInstance()的反射機(jī)制實(shí)例化Job。

1.5 ThreadPool

Scheduler使用一個(gè)線程池作為任務(wù)運(yùn)行的基礎(chǔ)設(shè)施锥忿,任務(wù)通過共享線程池中的線程提高運(yùn)行效率牛郑。
Job有一個(gè) StatefulJob 子接口(Quartz2后用@PersistJobDataAfterExecution注解代替),代表有狀態(tài)的任務(wù)敬鬓,改接口是一個(gè)沒有方法的標(biāo)簽接口淹朋,其目的是讓Quartz知道任務(wù)的類型,以便采用不同的執(zhí)行方案钉答。

  • 無狀態(tài)任務(wù)在執(zhí)行時(shí)擁有自己的 JobDataMap 拷貝础芍,對(duì) JobDataMap 的更改不會(huì)影響下次的執(zhí)行。

  • 有狀態(tài)任務(wù)共享同一個(gè) JobDataMap 實(shí)例数尿,每次任務(wù)執(zhí)行對(duì) JobDataMap 所做的更改會(huì)保存下來仑性,后面的執(zhí)行可以看到這個(gè)更改,也即每次執(zhí)行任務(wù)后都會(huì)對(duì)后面的執(zhí)行發(fā)生影響右蹦。

正因?yàn)檫@個(gè)原因诊杆,無狀態(tài)的Job能并發(fā)執(zhí)行歼捐,而有狀態(tài)的StatefulJob不能并發(fā)執(zhí)行。

1.6 Listener

Listener:Quartz擁有完善的事件和監(jiān)聽體系晨汹,大部分組件都擁有事件豹储,如:JobListener監(jiān)聽任務(wù)執(zhí)行前事件、任務(wù)執(zhí)行后事件淘这;TriggerListener監(jiān)聽觸發(fā)前事件剥扣,出發(fā)后事件;TriggerListener監(jiān)聽調(diào)度開始事件,關(guān)閉事件等等铝穷,可以注冊(cè)響應(yīng)的監(jiān)聽器處理感興趣的事件钠怯。


2.cronExpression 表達(dá)式

格式:[秒][分][時(shí)][每月的第幾日][月][每周的第幾日][年]

字段名 必填 允許值 允許特殊符號(hào)
Seconds YES 0 - 59 , - * /
Minutes YES 0- 59 , - * /
Hours YES 0-23 , - * /
Day of month YES 1-31 , - * ? / L W
Month YES 1-12 or JAN-DEC , - * /
Day of Week YES 1-7 or SUN-SAT , - * ? / L #
Year NO empty, 1970-2099 , - * /

特殊字符說明:

字段 含義
* 用于指定字段中所有值。比如:*在分鐘中表示每一分鐘
? 用于指定日期中的某一天氧骤,或是星期中的某一個(gè)星期
- 用于指定范圍吃引。比如:10-12在小時(shí)中表示 10點(diǎn)筹陵、11點(diǎn)、12點(diǎn)镊尺。
, 用于指定額外的值朦佩。比如:MON,WED,FRI在日期中表示星期一,星期三庐氮,星期五
/ 用于指定增量语稠。比如:0/15在秒中表示0秒,15秒弄砍,30秒仙畦,45秒5/15在秒鐘表示 5秒音婶,20秒慨畸,35秒,50秒衣式。
L 在兩個(gè)字段中擁有不同含義寸士。比如L在日期(Day of month)表示某月的最后一天。在星期(Day of week)只表示7SAT碴卧。但是弱卡,值L在星期(Day of week)中表示某月的最后一個(gè)星期幾。比如6L表示某月的最后一個(gè)星期五住册。也可以在日期中(Day of month)中指定一個(gè)偏移量(從該月最后一天開始)婶博。比如L-3表示某月的倒數(shù)第三天
W 用于指定工作日(星期一到星期五) 比如:15W在日期中表示到15號(hào)的最近一個(gè)工作日荧飞。如果15號(hào)是周六凡蜻,那么觸發(fā)器的觸發(fā)在14號(hào)星期五搭综。如果15號(hào)是周日,觸發(fā)器的觸發(fā)在15號(hào)周一划栓。如果十五號(hào)是星期二兑巾,那么它就會(huì)在15號(hào)周二開始執(zhí)行。然而 如果指定1W 并且1號(hào)是星期六忠荞,那么觸發(fā)器的觸發(fā)在3號(hào)周一蒋歌,因?yàn)樗粫?huì)“jump”過一個(gè)月的日子邊界。
LW 可以在日期(day-of-month)合使用委煤,表示月份的最后一個(gè)工作日堂油。
# 用于指定月份中的第幾天。比如:6#3表示月份的第三個(gè)星期五(day 6 = Friday and "#3" = the 3rd one in the month)碧绞。其它的有府框,2#1表示月份第一個(gè)星期一4#5表示月份第五個(gè)星期三讥邻。注意:如果只是指定#5迫靖,則觸發(fā)器在月份中不會(huì)觸發(fā)。

注意:字符不區(qū)分大小寫兴使,MON,mon相同系宜。

2.1 cornExpression示例

表達(dá)式 含義
0 0 12 * * ? 每天12點(diǎn)
0 15 10 ? * * 每天上午10點(diǎn) 15
0 15 10 * * ? 每天上午10點(diǎn) 15
0 15 10 * * ? * 每天上午10點(diǎn) 15
0 15 10 * * ? 2005 在2005年中每天的上午10點(diǎn)15
0 * 14 * * ? 每天14點(diǎn)-14點(diǎn)59分的每分鐘
0 0/5 14 * * ? 每天14點(diǎn) 到14點(diǎn)55 每5分鐘執(zhí)行一次
0 0/5 14,18 * * ? 每天14點(diǎn)到14點(diǎn)55 18點(diǎn)到18點(diǎn)55 每5分鐘執(zhí)行一次
0 0-5 14 * * ? 每天14點(diǎn)到14點(diǎn)5分 的每分鐘
0 10,44 14 ? 3 WED 3月每個(gè)星期三的 14點(diǎn)10分和44分
0 15 10 ? * MON-FRI 每周一到周五的10點(diǎn)15分
0 15 10 15 * ? 每月15號(hào)的10點(diǎn)15分
0 15 10 L * ? 每月的最后一天的10點(diǎn)15分
0 15 10 L-2 * ? 每月最后兩天的10點(diǎn)15分(每月的倒數(shù)第二天的10點(diǎn)15分?发魄?盹牧?(需驗(yàn)證))
0 15 10 ? * 6L 每月的最后一個(gè)周五10點(diǎn)15分
0 15 10 ? * 6L 2002-2005 02-05年 每月最后一個(gè)周五10點(diǎn)15
0 15 10 ? * 6#3 每月第三周的周五10點(diǎn)15分
0 0 12 1/5 * ? 每月1號(hào)到31號(hào) 每隔5天 12點(diǎn)0分
0 11 11 11 11 ? 每年11月11日11點(diǎn)11分

``


3.Listener示例

3.1注冊(cè)對(duì)特定作業(yè)的JobListener

scheduler.getListenerManager().addJobListener(
          new MyJobListener(),KeyMatcher.keyEquals(new JobKey("job1","group1")));

3.2注冊(cè)對(duì)特定組的所有作業(yè)的JobListener

scheduler.getListenManager().addJobListener(
          new MyJobListener(),GroupMatcher.jobGroupEquals("group1"));

3.3注冊(cè)對(duì)兩個(gè)特定組的所有作業(yè)的JobListener

scheduler.getListenManager().addJobListener(
          new MyJobListener(),OrMatcher.or(
                  GroupMatcher.jobGroupEquals("group1"),
                  GroupMatcher.jobGroupEquals("group2")));

3.4 注冊(cè)一個(gè)對(duì)所有作業(yè)的JobListener

sched.getListenerManager().addJobListener(
          new MyJobListener(),EverythingMatcher.allJobs());

3.5 JobListener 實(shí)現(xiàn)類

public class MyJobListener implements JobListener {

    @Override
    public String getName() {
        return "MyJobListener"; // 一定要設(shè)置名稱
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {

    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {

    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        if (jobException != null) {
            try {
                // 立即關(guān)閉調(diào)度器
                context.getScheduler().shutdown();
                System.out.println("Error occurs when executing jobs, shut down the scheduler.");
                // 給管理員發(fā)送郵件...
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    }
}

4.SchedulerListener 示例

SchedulerListener 在調(diào)度程序的Scheduler中注冊(cè)。SchedulerListener 可以運(yùn)行任何實(shí)現(xiàn) org.quartz.SchedulerListener 接口的對(duì)象励幼。

4.1 添加調(diào)度器的 SchedulerListener:

scheduler.getListenerManager().addSchedulerListener(mySchedListener);

4.2 刪除調(diào)度器的 SchedulerListener:

scheduler.getListenerManager().removeSchedulerListener(mySchedListener);

5.多線程并發(fā)執(zhí)行與數(shù)據(jù)共享

5.1禁止同一個(gè)JobDetail中的多個(gè)實(shí)例并發(fā)執(zhí)行

Quartz定時(shí)任務(wù)默認(rèn)都是并發(fā)執(zhí)行的汰寓。不會(huì)等待上一次任務(wù)執(zhí)行完畢,只要間隔時(shí)間到了就會(huì)執(zhí)行苹粟,如果定時(shí)任務(wù)執(zhí)行太長(zhǎng)踩寇,會(huì)長(zhǎng)時(shí)間占用資源。導(dǎo)致其它任務(wù)堵塞六水。(quartz是用一個(gè)線程池去執(zhí)行的俺孙。線程池有大小。如果同一任務(wù)并發(fā)執(zhí)行過多掷贾。影響線程池其它任務(wù)執(zhí)行)

禁止并發(fā)執(zhí)行的意思并不是不能同時(shí)執(zhí)行多個(gè)Job睛榄,而是不能并發(fā)執(zhí)行同一個(gè)Job Definition(由JobDetail定義),但是可以同時(shí)執(zhí)行多個(gè)不同的JobDetail想帅,舉例說明场靴,我們有一個(gè)Job類,叫做SayHelloJob,并在這個(gè)Job上加了@DisallowConcurrentExecution注解旨剥,然后再這個(gè)Job上定義了很多JobDetail咧欣,如sayHelloTomJobDetail,sayHelloMikeJobDetail轨帜,那么當(dāng)scheduler啟動(dòng)時(shí)魄咕,不會(huì)并發(fā)執(zhí)行多個(gè)sayHelloTomJobDetail 或者sayHelloMikeJobDetail 但可以同時(shí)執(zhí)行 sayHelloTomJobDetail跟sayHelloMikeJobDetail。

5.2 同一個(gè)JobDetail中多個(gè)實(shí)例的數(shù)據(jù)共享

@PersistJobDataAfterExecution 是用在Job實(shí)現(xiàn)類上蚌父,表示一個(gè)有狀態(tài)的任務(wù)哮兰,意思是當(dāng)正常執(zhí)行完Job后,JobDataMap中的數(shù)據(jù)會(huì)保存 給下一次調(diào)用使用苟弛。

注意:當(dāng)使用@persistJobDataAfterExecution注解時(shí)喝滞,為了避免并發(fā)時(shí),存儲(chǔ)數(shù)據(jù)造成混亂膏秫,強(qiáng)烈建議吧@DisallolwConcurrentExecution 注解也加上右遭。

示例

假設(shè)定時(shí)任務(wù)的時(shí)間間隔為 3 秒,但 job 執(zhí)行時(shí)間是 10 秒缤削。當(dāng)設(shè)置 @DisallowConcurrentExecution 以后程序會(huì)等任務(wù)執(zhí)行完畢后再去執(zhí)行窘哈,否則會(huì)在 3 秒時(shí)再啟動(dòng)新的線程執(zhí)行。

當(dāng)設(shè)置 @PersistJobDataAfterExecution 時(shí)僻他,在執(zhí)行完 Job 的 execution 方法后保存 JobDataMap 當(dāng)中固定數(shù)據(jù)宵距,以便任務(wù)在重復(fù)執(zhí)行的時(shí)候具有相同的 JobDataMap腊尚;在默認(rèn)情況下也就是沒有設(shè)置 @PersistJobDataAfterExecution 的時(shí)候每個(gè) job 都擁有獨(dú)立 JobDataMap吨拗。


6.Quartz 異常與中斷

6.1 作業(yè)異常

org.quartz.JobExecutionException會(huì)在Scheduler(調(diào)度器)運(yùn)行錯(cuò)誤時(shí),由Job(作業(yè))實(shí)現(xiàn)類拋出婿斥。

在我們捕獲異常并解決異常后劝篷,可以調(diào)用JobExecutionException#setRefireImmediately(true) 立即重新執(zhí)行作業(yè)。
假設(shè)我們有一個(gè)會(huì)拋出異常的job實(shí)現(xiàn)類民宿,job實(shí)現(xiàn)類的代碼片段如下

try {
    // 一個(gè)異常例子娇妓,假設(shè)第一次傳入的 denominator 為 0,那么將會(huì)拋出異常
    calculation = 4815 / denominator;
} catch (Exception e) {
    JobExecutionException e2 = new JobExecutionException(e);

    // 在第一次異常后活鹰,修改 denominator 參數(shù)為 1哈恰,那么后面的執(zhí)行就不會(huì)出錯(cuò)了
    dataMap.put("denominator", "1");

    // true 表示立即重新執(zhí)行作業(yè)
    e2.setRefireImmediately(true);
    throw e2;
}

上面的作樂會(huì)在第一次執(zhí)行時(shí)拋出java.lang.ArithmeticException: / by zero異常后,馬上又會(huì)執(zhí)行一次志群,之后都可以正常執(zhí)行作業(yè)着绷。

注意:為了共享在同一個(gè)JobDetail中的JobDataMap,我們需要再上面這個(gè)Job實(shí)現(xiàn)類上加入@PersistJobDataAfterExecution 和 @DisallowconcurrentExecution注解锌云。

6.3 捕獲異常荠医,取消所有觸發(fā)器

在我們捕獲異常時(shí),可以調(diào)用JobExecutionException#setUnscheduleAllTriggers(true)取消所有與這個(gè)作業(yè)有關(guān)的觸發(fā)器。
假設(shè)我們有一個(gè)會(huì)爆出一場(chǎng)的job實(shí)現(xiàn)類彬向,job實(shí)現(xiàn)類代碼片段如下:

try {
    // 一個(gè)異常例子
    int zero = 0;
    calculation = 4815 / zero;
} catch (Exception e) {
    JobExecutionException e2 = new JobExecutionException(e);
    // true 表示 Quartz 會(huì)自動(dòng)取消所有與這個(gè) job 有關(guān)的 trigger兼贡,從而避免再次運(yùn)行 job
    e2.setUnscheduleAllTriggers(true);
    throw e2;
}

上面的作業(yè)會(huì)在拋出異常后,就不再執(zhí)行任何有關(guān)該作業(yè)的觸發(fā)器了娃胆。

6.3 作業(yè)中斷

org.quartz.InterruptableJob接口提供了一種中斷機(jī)制遍希,這個(gè)接口只有一個(gè)方法interrupt() 這個(gè)方法會(huì)在用戶發(fā)出中斷請(qǐng)求到Scheduler(調(diào)度器)時(shí)觸發(fā)(即調(diào)用Scheduler#interrupt(JobDetail#getKey())方法時(shí)觸發(fā))

其中InterruptableJob接口又繼承了Job接口,所以當(dāng)我們使用時(shí)缕棵,只需要實(shí)現(xiàn)InterruptableJob接口孵班,重寫其中的executeinterrupt方法即可。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末招驴,一起剝皮案震驚了整個(gè)濱河市篙程,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌别厘,老刑警劉巖虱饿,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異触趴,居然都是意外死亡氮发,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門冗懦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爽冕,“玉大人,你說我怎么就攤上這事披蕉【被” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵没讲,是天一觀的道長(zhǎng)眯娱。 經(jīng)常有香客問我,道長(zhǎng)爬凑,這世上最難降的妖魔是什么徙缴? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮嘁信,結(jié)果婚禮上于样,老公的妹妹穿的比我還像新娘。我一直安慰自己潘靖,他們只是感情好穿剖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秘豹,像睡著了一般携御。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天啄刹,我揣著相機(jī)與錄音涮坐,去河邊找鬼。 笑死誓军,一個(gè)胖子當(dāng)著我的面吹牛袱讹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播昵时,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼捷雕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了壹甥?” 一聲冷哼從身側(cè)響起救巷,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎句柠,沒想到半個(gè)月后浦译,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溯职,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年精盅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谜酒。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叹俏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出僻族,到底是詐尸還是另有隱情粘驰,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布鹰贵,位于F島的核電站晴氨,受9級(jí)特大地震影響康嘉,放射性物質(zhì)發(fā)生泄漏碉输。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一亭珍、第九天 我趴在偏房一處隱蔽的房頂上張望敷钾。 院中可真熱鬧,春花似錦肄梨、人聲如沸阻荒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侨赡。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間羊壹,已是汗流浹背蓖宦。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留油猫,地道東北人稠茂。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像情妖,于是被迫代替她去往敵國(guó)和親睬关。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • scheduler定時(shí)調(diào)度系統(tǒng)是大多行業(yè)項(xiàng)目都需要的毡证,傳統(tǒng)的spring-job模式电爹,個(gè)人感覺已經(jīng)out了,因?yàn)榇?..
    安琪拉_4b7e閱讀 2,841評(píng)論 4 6
  • 什么是定時(shí)任務(wù)調(diào)度 基于給定的時(shí)間點(diǎn)料睛,給定的時(shí)間間隔或者給定的執(zhí)行次數(shù)自動(dòng)完成執(zhí)行任務(wù) 在Java中的定時(shí)調(diào)度工具...
    Hey_Shaw閱讀 2,512評(píng)論 2 1
  • Quartz是一個(gè)完全由java編寫的功能豐富的開源作業(yè)調(diào)度庫(kù)藐不,可以集成到幾乎任何Java應(yīng)用程序中,小到獨(dú)立應(yīng)用...
    ProteanBear閱讀 7,083評(píng)論 3 24
  • 入門簡(jiǎn)介: 基本上任何公司都會(huì)用到調(diào)度這個(gè)功能秦效, 比如我們公司需要定期執(zhí)行調(diào)度生成報(bào)表雏蛮, 或者比如博客什么的定時(shí)更...
    水車閱讀 6,288評(píng)論 0 9
  • 胖頭頓時(shí)歡樂了,一路上朱臉七都在吹噓山貓和土耗子都得了他的真?zhèn)髭逯荩瑳]想到竟然是這么個(gè)情況挑秉。胖頭明顯是唯恐天下不亂的那...
    青檸芝夏閱讀 299評(píng)論 0 0