簡(jiǎn)單了解Quartz

Quartz是一個(gè)任務(wù)調(diào)度框架缰泡,主要用來操作定時(shí)任務(wù)刀荒。Quartz主要使用的模式是工廠模式和Builder模式
Quartz的核心主要有:
1. Scheduler: 調(diào)度器,主要用來調(diào)度任務(wù)
2. Job:調(diào)度任務(wù),任務(wù)的業(yè)務(wù)邏輯都在這里面編寫
3. JobDetail: Job的封裝器缠借,用于定義Job的數(shù)據(jù)
4. Trigger:任務(wù)觸發(fā)器干毅,用于設(shè)定觸發(fā)時(shí)間
5. JobBuilder:任務(wù)構(gòu)建器,用于創(chuàng)建JobDetail
6. TriggerBuilder:用于創(chuàng)建Trigger

quartz核心.png

maven依賴:

<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.2</version>
</dependency>
/**
 * job具體邏輯
 * Created by Sanisy on 2018/2/16.
 */
public class HelloJob implements Job{

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(format.format(new Date()));
        //獲取JobDetail定義的參數(shù)值
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        System.out.println("userName=" + jobDataMap.getString("userName"));
        System.out.println("email=" + jobDataMap.getString("email"));
        System.out.println("msg=" + jobDataMap.getString("msg"));
    }
}

public class Main {

    public static void main(String[] args) throws Exception{
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();

        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.start();

        // define the job and tie it to our HelloJob class
        JobDetail job = JobBuilder.newJob(HelloJob.class)
                .withIdentity("myJob", "group1")
                .usingJobData("userName", "Sanisy")
                .usingJobData("email", "sanisyme@163.com")
                .usingJobData("msg", "you should be know nginx泼返、 redis硝逢、zookeeper、netty绅喉、dubbo渠鸽、spring cloud、elasticsearch")
                .build();

        // Trigger the job to run now, and then every 40 seconds
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("myTrigger", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(2)
                        .repeatForever())
                .build();

        // Tell quartz to schedule the job using our trigger
        scheduler.scheduleJob(job, trigger);

    }
}
執(zhí)行結(jié)果截圖.png

Trigger有兩種調(diào)度設(shè)置方式柴罐,一種是SimpleScheduleBuilder徽缚,另外一種是CronScheduleBuilder。SimpleScheduleBuilder只是簡(jiǎn)單地設(shè)置幾分幾秒幾小時(shí)為周期的任務(wù)調(diào)度丽蝎;CronScheduleBuilder使用的是linux系統(tǒng)的cron表達(dá)式猎拨,支持更加復(fù)雜的設(shè)置,可以定時(shí)到哪天哪個(gè)時(shí)間節(jié)點(diǎn)開始屠阻,還可以設(shè)置循環(huán)周期红省。

public class Main {

    public static void main(String[] args) throws Exception{
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();

        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.start();

        // define the job and tie it to our HelloJob class
        JobDetail job = JobBuilder.newJob(HelloJob.class)
                .withIdentity("myJob", "group1")
                .usingJobData("userName", "Sanisy")
                .usingJobData("email", "sanisyme@163.com")
                .usingJobData("msg", "you should be know nginx、 redis国觉、zookeeper吧恃、netty、dubbo麻诀、spring cloud痕寓、elasticsearch")
                .build();

        // Trigger the job to run now, and then every 40 seconds
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("myTrigger", "group1")
                .startNow()
                .withSchedule(CronScheduleBuilder.cronSchedule("0 0/1 * * * ?")) //每分鐘執(zhí)行一次
                .build();

        // Tell quartz to schedule the job using our trigger
        scheduler.scheduleJob(job, trigger);

    }
}
cron方式運(yùn)行結(jié)果.png

通過上面的執(zhí)行日志,我們可以看到Quartz的最終執(zhí)行Job的execute方法是在JobRunShell中:

public class JobRunShell extends SchedulerListenerSupport implements Runnable {
    /**
     * <p>
     * Create a JobRunShell instance with the given settings.
     * </p>
     *
     * @param scheduler
     *          The <code>Scheduler</code> instance that should be made
     *          available within the <code>JobExecutionContext</code>.
     */
    public JobRunShell(Scheduler scheduler, TriggerFiredBundle bndle) {
        this.scheduler = scheduler;
        this.firedTriggerBundle = bndle;
    }

    public void initialize(QuartzScheduler sched)
        throws SchedulerException {
        this.qs = sched;

        Job job = null;
        JobDetail jobDetail = firedTriggerBundle.getJobDetail();
        job = sched.getJobFactory().newJob(firedTriggerBundle, scheduler);
        //創(chuàng)建Job的上下文
        this.jec = new JobExecutionContextImpl(scheduler, firedTriggerBundle, job);
    }
    
    //這里只顯示了核心部分蝇闭,刪除了大部分代碼
    public void run() {
      do {
          JobExecutionException jobExEx = null;
          Job job = jec.getJobInstance();
          job.execute(jec);
      }while (true);
    }
}

值得注意的是呻率,Quartz默認(rèn)是采用線程池來執(zhí)行Job任務(wù)的,所以多個(gè)任務(wù)會(huì)被并發(fā)執(zhí)行,也就是說Quartz不會(huì)等待上一個(gè)時(shí)間節(jié)點(diǎn)任務(wù)執(zhí)行完畢才去執(zhí)行下一個(gè)時(shí)間節(jié)點(diǎn)任務(wù)呻引。在一些場(chǎng)景下可以通過注解@DisallowConcurrentExecution來避免重復(fù)操作某些數(shù)據(jù)礼仗。
更多細(xì)節(jié)請(qǐng)參考:
官方文檔
路邊飛~~~的博客
Quartz相對(duì)于Spring Schedule的優(yōu)點(diǎn)是它支持分布式,而 schedule 不支持(需要自己實(shí)現(xiàn),用分布式鎖)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末逻悠,一起剝皮案震驚了整個(gè)濱河市元践,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌童谒,老刑警劉巖单旁,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異饥伊,居然都是意外死亡象浑,警方通過查閱死者的電腦和手機(jī)蔫饰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來融柬,“玉大人死嗦,你說我怎么就攤上這事×Q酰” “怎么了越除?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)外盯。 經(jīng)常有香客問我摘盆,道長(zhǎng),這世上最難降的妖魔是什么饱苟? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任孩擂,我火速辦了婚禮,結(jié)果婚禮上箱熬,老公的妹妹穿的比我還像新娘类垦。我一直安慰自己,他們只是感情好城须,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布蚤认。 她就那樣靜靜地躺著,像睡著了一般糕伐。 火紅的嫁衣襯著肌膚如雪砰琢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天良瞧,我揣著相機(jī)與錄音陪汽,去河邊找鬼。 笑死褥蚯,一個(gè)胖子當(dāng)著我的面吹牛挚冤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赞庶,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼训挡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了尘执?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤宴凉,失蹤者是張志新(化名)和其女友劉穎誊锭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弥锄,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丧靡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年蟆沫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片温治。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饭庞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出熬荆,到底是詐尸還是另有隱情舟山,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布卤恳,位于F島的核電站累盗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏突琳。R本人自食惡果不足惜若债,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拆融。 院中可真熱鬧蠢琳,春花似錦、人聲如沸镜豹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逛艰。三九已至躏碳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間散怖,已是汗流浹背菇绵。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留镇眷,地道東北人咬最。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像欠动,于是被迫代替她去往敵國(guó)和親永乌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354