1. 程式人生 > >Java定時任務工具Quartz——學習筆記(一)

Java定時任務工具Quartz——學習筆記(一)

最近在準備做一個生日提醒的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分觸發(光棍節)