企業(yè)任務(wù)調(diào)度框架Quartz入門

定時任務(wù)蝙叛,無論是互聯(lián)網(wǎng)行業(yè)還是傳統(tǒng)軟件行業(yè)都是不可少的俺祠。今天介紹的Quartz就是一款非常優(yōu)秀的企業(yè)任務(wù)調(diào)度框架。

Quartz簡介

Quartz是OpenSymphony開源組織在Job scheduling領(lǐng)域的又一開源項(xiàng)目借帘,它可以和J2EE或J2SE程序結(jié)合使用也可以單獨(dú)使用蜘渣。小到獨(dú)立的應(yīng)用,大到電子商業(yè)系統(tǒng)肺然,Quartz都能夠創(chuàng)建執(zhí)行成百上千甚至上萬的任務(wù)蔫缸。簡而言之就是Quartz是基于Java實(shí)現(xiàn)的任務(wù)調(diào)度框架,可以執(zhí)行你想執(zhí)行的任何任務(wù)际起。

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

Job
Job就是你想要實(shí)現(xiàn)的任務(wù)類拾碌,每一個Job必須實(shí)現(xiàn)org.quartz.job接口,且只需實(shí)現(xiàn)接口定義的execute方法加叁。

JobDetail
JobDetail為Job實(shí)例提供了許多設(shè)置屬性以及JobDataMap成員變量屬性,它用來存儲特定Job實(shí)例的狀態(tài)信息唇撬。常見屬性name它匕、group、jobClass窖认、jobDataMap等

Trigger
觸發(fā)器豫柬,Trigger就是你執(zhí)行任務(wù)的觸發(fā)器,定時去觸發(fā)你想要執(zhí)行的任務(wù)扑浸。Trigger主要分為SimpleTrigger和CronTrigger兩種烧给。

Scheduler
調(diào)度器,將任務(wù)Job和觸發(fā)器Trigger整合起來喝噪,負(fù)責(zé)根據(jù)Trigger設(shè)定的時間執(zhí)行Job础嫡。


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

入門例子

需求:每隔5秒鐘控制臺輸出一下當(dāng)前時間,并傳遞數(shù)據(jù)給任務(wù)類。

/**
 * 定義要執(zhí)行的任務(wù)類
 *  1.必須實(shí)現(xiàn)Job接口
 *  2.實(shí)現(xiàn)接口中的execute方法, 在該方法中編寫任務(wù)執(zhí)行的業(yè)務(wù)邏輯
 *  3.每次執(zhí)行Job時, 都會在調(diào)用execute方法前創(chuàng)建一個新的Job實(shí)例, 調(diào)用完成后, Job實(shí)例就會被釋放
 */
public class MyJob implements Job {

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //1.獲取當(dāng)前時間
        LocalTime localTime = LocalTime.now();
        System.out.println("當(dāng)前時間: "+localTime);
        //2.獲取trigger傳遞的數(shù)據(jù)
        String name = jobExecutionContext.getTrigger().getJobDataMap().getString("name");
        System.out.println("觸發(fā)器傳遞數(shù)據(jù):"+name);
        //3.獲取jobDetail傳遞的數(shù)據(jù)
        int count = jobExecutionContext.getJobDetail().getJobDataMap().getInt("count");
        System.out.println("JobDetail傳遞數(shù)據(jù):"+count);
    }

}
public static void main(String[] args) throws Exception{
    //1.定義任務(wù)調(diào)度器Scheduler并啟動
    Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
    scheduler.start();

    /**
     * 定義定時任務(wù)的實(shí)例JobDetail
     *    1.通過JobBuilder創(chuàng)建
     *    2.JobDetail為Job提供了很多設(shè)置屬性, 用來存儲Job實(shí)例的狀態(tài)信息
     */
    JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                                    //設(shè)置任務(wù)名稱和任務(wù)組名
                                    .withIdentity("myjob", "job-group")
                                    //設(shè)置JobDataMap, 可以在MyJob任務(wù)類中獲取到
                                    .usingJobData("count", 10)
                                    .build();

    //3.定義觸發(fā)器Trigger
    Trigger trigger = TriggerBuilder.newTrigger()
                                     //設(shè)置觸發(fā)器名稱和觸發(fā)器組名
                                    .withIdentity("trigger", "trigger-group")
                                    //設(shè)置JobDataMap, 可以在MyJob任務(wù)類中獲取到
                                    .usingJobData("name", "zhangsan")
                                     //每5秒觸發(fā)一次
                                    .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
                                    .build();

    //4.通過調(diào)度器關(guān)聯(lián)任務(wù)和觸發(fā)器
    scheduler.scheduleJob(jobDetail, trigger);
}

輸出:
當(dāng)前時間: 16:56:27.579
觸發(fā)器傳遞數(shù)據(jù):zhangsan
JobDetail傳遞數(shù)據(jù):10
當(dāng)前時間: 16:56:32.509
觸發(fā)器傳遞數(shù)據(jù):zhangsan
JobDetail傳遞數(shù)據(jù):10
....

Job

定時任務(wù)并發(fā)執(zhí)行問題

在任務(wù)類上加@DisallowConcurrentExecution即可解決并發(fā)問題

@DisallowConcurrentExecution
public class MyJob implements Job {
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
    }
}

Job狀態(tài)

Job分為有狀態(tài)的Job和無狀態(tài)的Job
有狀態(tài)的Job:多次Job調(diào)用期間可以持有一些狀態(tài)信息榴鼎,這些信息存儲在JobDataMap中
無狀態(tài)的Job:每次調(diào)用都會創(chuàng)建一個新的JobDataMap

# 沒有添加該注解伯诬,每次調(diào)用創(chuàng)建一個新的JobDataMap,不會累加
# 添加該注解巫财,多次Job調(diào)用可以持有一些狀態(tài)信息
@PersistJobDataAfterExecution
public class HelloJob implements Job {
}

Trigger

Simple觸發(fā)器

簡單的觸發(fā)器盗似,適合于按照時間間隔重復(fù)執(zhí)行一項(xiàng)定時任務(wù)。

常用屬性:開始時間平项、結(jié)束時間赫舒、重復(fù)次數(shù)和重復(fù)間隔
重復(fù)次數(shù):0、正整數(shù)闽瓢、無限次執(zhí)行
重復(fù)間隔:0(并發(fā)執(zhí)行)接癌、long類型(毫秒級)

Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger-name", "trigger-group")
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                                    .withIntervalInSeconds(5) //時間間隔:5秒
                                    .withRepeatCount(100)     //重復(fù)執(zhí)行100次
                    )
                    .startAt(DateBuilder.futureDate(10, DateBuilder.IntervalUnit.SECOND)) //10秒后開始執(zhí)行
                    .endAt(DateBuilder.futureDate(50, DateBuilder.IntervalUnit.SECOND))   //50秒后結(jié)束
                    .build();

Cron觸發(fā)器

按日歷方式觸發(fā)任務(wù)。

Cron表達(dá)式:由7個字表達(dá)式組成的字符串鸳粉,每個表達(dá)式都描述了一個單獨(dú)的日程細(xì)節(jié)扔涧,表達(dá)式使用空格分割
1.秒
2.分
3.小時
4.天(月)
5.月
6.天(周)
7.年

字段 必須 特殊符號
0-59 , - * /
0-59 , - * /
0-23 , - * /
天(月) 1-31 , - * / ? L W C
1-12 或 JAN-DEC , - * /
1-7 或 SUN-SAT , - * / ? L C #
不填寫 或 1970-2099 , - * /
特殊符號 含義
* 用來表示域中每個可能的值
? 不指定值,忽略這個值
- 表示區(qū)間届谈,比如3-5枯夜,就表示3,4,5
, 指定多個值, 比如3,4,5
/ 表示值的增量艰山,例如分鐘域上0/2表示每個2分鐘從0開始
L last的簡寫湖雹,day of month中表示這個月的最后一天,day of week表示7(周六)曙搬,在day of week域中6L表示最后一周的周5
W 用來指定距離給定日最近的周幾(在day of week域中指定)摔吏,例如day of month域中指定12W表示距離12號最近的周幾
# 表示月中第幾個周幾,day of week中6#3表示月中第三個周五

示例
0 0 2,4,20 * * ? 每天上午2點(diǎn)4點(diǎn), 下午20點(diǎn)執(zhí)行
0 0/30 9-20 * * ? 每天早上9點(diǎn)到20點(diǎn)每隔半個小時執(zhí)行一次
0 0 12 纵装? * WED 每個周三中午12點(diǎn)
0 0 12 * * 征讲? 每天中午12點(diǎn)觸發(fā)
0 * 14 * * ? 每天下午14點(diǎn)到14點(diǎn)59每隔一分鐘執(zhí)行一次

Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1") //觸發(fā)器名稱橡娄,觸發(fā)器組名稱
        //每5秒執(zhí)行一次
        .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
        .build();

Trigger的優(yōu)先級問題

Trigger默認(rèn)優(yōu)先級為5诗箍,只有在多個Trigger同時執(zhí)行,并且線程數(shù)小于Trigger數(shù)量時才會有用挽唉。

    Trigger trigger = TriggerBuilder.newTrigger()
                                    .withIdentity("trigger", "trigger-group")
                                    .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
                                    .withPriority(6) //設(shè)置Trigger的優(yōu)先級為6
                                    .build();

Scheduler調(diào)度器

StdSchedulerFactory

默認(rèn)創(chuàng)建Scheduler的方式滤祖,使用一組參數(shù)(java.util.Properties)來創(chuàng)建和初始化Quartz調(diào)度器。
配置參數(shù)我們可以存儲在quartz.properties
調(diào)用getScheduler方法就能創(chuàng)建和初始化調(diào)度器對象

# 方式1
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();

# 方式2
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

Scheduler

調(diào)度器瓶籽,將任務(wù)Job和觸發(fā)器Trigger整合起來匠童,負(fù)責(zé)根據(jù)Trigger設(shè)定的時間執(zhí)行Job。

//將任務(wù)Job和觸發(fā)器Trigger整合起來塑顺, 并返回調(diào)度器開始時間
Date date = scheduler.scheduleJob(jobDetail, trigger);
//開啟任務(wù)調(diào)度
scheduler.start();
//掛起汤求,即暫停操作
scheduler.standby();
//等所以正在執(zhí)行的任務(wù)執(zhí)行完畢滔驶,再關(guān)閉
scheduler.shutdown(true); 
//直接關(guān)閉
scheduler.shutdown(false);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仍劈,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌参咙,老刑警劉巖缆毁,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甩十,死亡現(xiàn)場離奇詭異濒募,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)赊颠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門格二,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人竣蹦,你說我怎么就攤上這事顶猜。” “怎么了痘括?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵长窄,是天一觀的道長。 經(jīng)常有香客問我纲菌,道長挠日,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任翰舌,我火速辦了婚禮嚣潜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘椅贱。我一直安慰自己懂算,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布庇麦。 她就那樣靜靜地躺著计技,像睡著了一般。 火紅的嫁衣襯著肌膚如雪山橄。 梳的紋絲不亂的頭發(fā)上垮媒,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機(jī)與錄音驾胆,去河邊找鬼涣澡。 笑死贱呐,一個胖子當(dāng)著我的面吹牛丧诺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奄薇,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼驳阎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起呵晚,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蜘腌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后饵隙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撮珠,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年金矛,在試婚紗的時候發(fā)現(xiàn)自己被綠了芯急。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡驶俊,死狀恐怖娶耍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饼酿,我是刑警寧澤榕酒,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站故俐,受9級特大地震影響想鹰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜购披,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一杖挣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刚陡,春花似錦惩妇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蝙云,卻和暖如春氓皱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勃刨。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工波材, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人身隐。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓廷区,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贾铝。 傳聞我的和親對象是個殘疾皇子隙轻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

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