一、quartz
1.相關API介紹:
(1)Scheduler是與程式互動的主要API,主要是用于執行計劃的,schedule由scheduler工廠建立,工廠包括DirectSchedulerFactory 或者 StdSchedulerFactory,後者用的比較多,比較友善
(2)Job是自定義作業需要實作的接口,job分為stateless無狀态和stateful有狀态,
trigger隻執行無狀态的任務,即一個任務不能被并行執行;一個job可被多個trigger關聯,一個trigger隻能關聯一個job,
job的兩個屬性:volatility 和 durability,其中 volatility 表示任務是否被持久化到資料庫存儲,而 durability 表示在沒有 trigger 關聯的時候任務是否被保留,
兩者都是在值為 true 的時候任務被持久化或保留
(3)JobDetail定義作業執行個體,作業名稱群組别等
(4)Trigger定義觸發器,即執行作業的時間計劃,有四種類型:SimpleTrigger,CronTirgger,DateIntervalTrigger,和 NthIncludedDayTrigger,
SimpleTrigger用于在某個特定時間隻執行一次的;Crontirgger 用的多一些,
simpleTrigger主要是做間隔執行任務的,不太适合定時執行任務,對于某些日期或者周幾執行的這種情況 甚至隻能使用crontrigger
(5)TriggerBuilder 用于建構出觸發器執行個體
(6)JobBuilder 建構Jobe執行個體
2.quartz是spring預設的排程架構
3.quartz資料存儲包括兩種存儲方式:RAMJobStore, JobStoreSupport,前者基于記憶體,後者DB,後者持久用的多
4.同一個分組下的Job或Trigger的名稱必須唯一,即一個Job或Trigger的key由名稱(name)和分組(group)組成。
5.JobDetail對象中有JobDataMap,可以在建構JobDetail時用來傳資料,然後在excute方法上下文中取到
6.JobExecutionContext 這個execute方法的參數是定時任務的上下文,其中有目前scheduler、trigger、job以及jobDetail中所有的資料
7.Trigger:
(1)公共屬性:
key:由name和group組成唯一
startTime 任務首次觸發的參照時間,有些是starttime立即觸發,有些是starttime之後一段時間觸發
endTime trigger失效的時間
priority 優先級, 當quartz線程池資源少,而trigger比較多時,同時觸發的trigger之間優先級高的會先被線程執行,優先級預設都是5,可以為任意整數
觸發時間不同的,觸發時間早的總是優先執行,與priority無關
misfire: 錯過觸發,如果scheduler中沒有足夠的線程來執行trigger,那麼就會錯過觸發時間,此時要執行的政策,就是misfire,
不同類型的trigger有不同的misfire,所有trigger有預設的smart misfire,會根據配置動态選擇一個misfire的政策
(2) 常見trigger介紹
i.simpleTrigger
滿足的排程需求是:任務在某個具體時間執行一次或者以指定的間隔重複執行若幹次,屬性包括開始時間,結束時間,執行間隔和執行次數,
它所有的misfire看具體說明
ii.CronTrigger
比simpleTrigger更常用,是基于月曆的一個trigger
Cron Expressions:
表達式中的值都表示的是某一個時刻點
0 * 17 * * ?
意義:每天從下午5點到下午5:59中的每分鐘激發一次 trigger。它停在下午5:59 是因為值 17 在小時域上,在下午 6 點時,小時變為 18 了,也就不再理會這個trigger,直到下一天的下午5點。
在你希望 trigger 在該域的所有有效值上被激發時使用* 字元。
秒 分 時 月中日 月 周中日 年(可選字段)
通配符表示每個可能的值 ,;
?隻能用于日期和星期的一個,表示沒有特定值,隻是占位而已,spring規定日期和星期有且隻能有一個,另一個就是?表示占位,
看下面的表達式測試
/用于指定值的增量,如: 分鐘處是 3/10 則表示分針走到3時開始,然後每隔20分鐘執行一次 ,如果是增量,那麼 0/3和/3是一樣的* 執行時包括初始時刻,看測試
月份的0-11表示1-12月份, 星期的1-7表示星期日-星期六,也可用單詞前三位大寫表示:JAN FEB等
8.Calendar:
與java.util中的Calendar不同,用來從trigger的某些計劃中排除掉某些時間段,一個calendar執行個體化後,可用于多個trigger,用法如下
9.參考:w3cschool https://www.w3cschool.cn/quartz_doc/quartz_doc-lwuv2d2a.html
public static void main(String[] args) {
//排程工廠
StdSchedulerFactory std = new StdSchedulerFactory();
//排程器
Scheduler scheduler =std.getScheduler();
//排程開始,一般shutdown的話排程就會結束,跟線程池的使用類似
scheduler.start();
//添加資料集,在job的excute裡可以擷取
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("mother","11");
jobDataMap.put("uncle","qq");
//calendar排除一整天,calender必須執行個體化,然後注冊到scheduler中
HolidayCalendar calendar = new HolidayCalendar();
//排除掉今天
calendar.addExcludedDate(new Date());
scheduler.addCalendar("myCalender",calendar,false,false);
//name和group組成了這個job唯一的JobKey
JobDetail jobMike = JobBuilder.newJob(Myjob.class).withIdentity("jobMike","group1")
//這裡的durable預設是false的,作業是否在沒有trigger與之關聯時仍然儲存
.usingJobData("processor","Mike").storeDurably(true).setJobData(jobDataMap).build();
//這裡的key由name和group組成,構成了triggerKey 同一個分組下要唯一
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger").
//每天10.25執行一次,但是不包括calendar中的那天
startNow().withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(10, 26))
.modifiedByCalendar("myCalender").withPriority(10).build();
//trigger公共屬性
System.out.println(trigger.getKey());
System.out.println("starttime:"+trigger.getStartTime());
System.out.println("endtime:"+trigger.getEndTime());
System.out.println("priority:"+trigger.getPriority());
//同一個job可以隻添加到計劃中,然後跟不同的多個trigger綁定,實作複雜排程計劃
scheduler.addJob(jobMike,false);
scheduler.scheduleJob(cronTriggerTest(jobMike));
scheduler.scheduleJob(cronTriggerTest1(jobMike));
}
//simpleTrigger舉例
public static Trigger simpleTriggerTest(){
//使用DateBuilder構造date,指定任意時間
Date date = DateBuilder.dateOf(20, 44, 30);
//目前時間30s後執行
Date futureDate = DateBuilder.futureDate(30, DateBuilder.IntervalUnit.SECOND);
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("mySimple","group1")
//這裡的simpleSchedule與simpleTrigger對應,最終構造出來就是simpleTrigger,
// withIntervalInSeconds或者withIntervalInHours()等是間隔時間,
// withRepeatCount(5)是重複次數,重複5次 則最終會執行6次 ,不限次數則repeatForever()
.startAt(futureDate).withSchedule(simpleSchedule().withIntervalInSeconds(2).withRepeatCount(5))
.withPriority(10).build();
//endAt 何時結束,這個表明立即觸發,date點時結束
SimpleTrigger trigger1 = TriggerBuilder.newTrigger().withIdentity("mySimple","group1")
.endAt(date).withSchedule(simpleSchedule().repeatForever())
.withPriority(10).build();
//觸發器:在下一個小時的整點觸發,每兩分鐘執行一次
//這個evenHourDate/evenMinuteDate是給定一個date然後拿這個date的下一個整點時間,null的話會new Date()
Date date1 = DateBuilder.evenMinuteDate(null);
SimpleTrigger trigger2 = TriggerBuilder.newTrigger().startAt(date1).
withSchedule(simpleSchedule().repeatForever().withIntervalInSeconds(2)).build();
return trigger2;
}
//cronTrigger舉例
public static Trigger cronTriggerTest(JobDetail jobDetail){
//cron expression
String cron0 = "0/2 * * * * ?";//每兩秒執行一次
String cron1 = "10 0/2 * * * ?";//每兩分鐘到了之後10s執行
String cron2 = "0 30 10-13 ? * 4,6";//每周三和周五的10:30 11:30 12:30 13:30執行,有星期的話月份日就要?占位
String cron3 = "0 0/30 8,9 5,20 * ?"; //每個月5号和20号上午8 8:30 9 9:30執行
String cron4 = "0 0/5 9-10 * * ?"; //
CronTrigger cronTrigger = TriggerBuilder.newTrigger().
withSchedule(CronScheduleBuilder.cronSchedule(cron0)).forJob(jobDetail).build();
return cronTrigger;
}
//自定義一個任務,需要實作Job接口
public class Myjob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
System.out.println("processor is "+jobDataMap.getString("processor"));
for (Map.Entry<String, Object> stringObjectEntry : jobDataMap.entrySet()) {
System.out.println(stringObjectEntry.getKey()+stringObjectEntry.getValue());
}
System.out.println(jobDetail.getKey().getName());
System.out.println(jobDetail.getKey().getGroup());
System.out.println("這是一個測試用的quartz的job");
}
}
10.quartz叢集搭建:
參考:https://www.jb51.net/article/139597.htm
(1)資料庫刷11張表
(2)叢集是通過DB感應彼此的,彼此之間沒有心跳感應
(3)代碼實作: 叢集之間的配置檔案和心跳代碼必須完全一樣
自定義job實作:
package com.sf.express.config.quartz.job;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import java.util.Date;
@Slf4j
@Component
public class HeartBeatJob extends QuartzJobBean {
//bean隻能從spring上下文中擷取
static RedisUtil redisUtil;
屬性的處理
@Autowired
public void setRedis(RedisUtil redisUtil1){
redisUtil1 = redisUtil1;
}
//定時任務,每2分鐘走一次
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
方法裡用到的spring的bean,隻能從容器上下文中去重新拿,這裡的調用時quartz重新反射了一個執行個體,不是spring中的bean
log.info("---定時任務開始---{}",new Date());
if (redisUtil==null){
redisUtil = (RedisUtil)SpringUtil.getBean(RedisUtil.class);
}
if(qrVisWgtDataMapper==null){
qrVisWgtDataMapper = (QrVisWgtDataMapper)SpringUtil.getBean(QrVisWgtDataMapper.class);
}
Object heartObj = redisUtil.get("heartbeat");
...
}
}
springboot中自動配置quartz的實作:
叢集環境下的quartz一定不能随便更改類似cronExp或者trigger名稱這些,每個屬性都會入庫,改了就出問題
quartz原理圖,其實就是将多個任務扔到排程容器中,将多個trigger扔到容器中,然後再将trigger和job綁定起來,綁定的過程在trigger的建立過程中,
是以一般來說一個應用一個排程器就夠了

/**
* @Description: 注冊定時任務
*/
@Configuration
public class QuartzConfiguration {
//cron表達式會入庫,同一個trigger表達式會在第一次寫入後不再寫入,如果要變執行計劃,可以增加一個trigger
private String cronExpression = "0 */2 * * * ?";
@Autowired
DataSource dataSource;
private static final String QUARTZ_CONFIG = "/quartz.properties";
private static final String JOB_NAME= "heartBeanJob";
private static final String TRIGGER_NAME= "heartBeanTrigger";
/**
* @Author: 01398017
* @Description: 讀取屬性檔案
* @DateTime: 2020/8/6
* @Params:
* @Return
*/
public Properties getProperties() {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource(QUARTZ_CONFIG));
try {
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Bean
public SchedulerFactoryBean getScheduler(@Qualifier(TRIGGER_NAME) Trigger heartBeatTrigger,
@Qualifier(DELETE_HISTORY_DATA_TRIGGER_NAME) Trigger deletingTrigger,
@Qualifier(JOB_NAME) JobDetail heartBeat,
@Qualifier(DELETE_JOB) JobDetail deletingJob ) {
SchedulerFactoryBean stdSchedulerFactory = new SchedulerFactoryBean();
//這裡設定是否自動開啟scheduler,預設true
stdSchedulerFactory.setAutoStartup(false);
//設定配置檔案
stdSchedulerFactory.setQuartzProperties(getProperties());
stdSchedulerFactory.setDataSource(dataSource);
//添加任務,這裡可以添加多個jobdetails,demo裡隻建立了一個trigger和job,另一個建立的類似
stdSchedulerFactory.setJobDetails(heartBeat,deletingJob);
//添加多個觸發器
stdSchedulerFactory.setTriggers(heartBeatTrigger,deletingTrigger);
try {
stdSchedulerFactory.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
stdSchedulerFactory.start();
return stdSchedulerFactory;
}
@Bean
public Trigger getCronTrigger(@Qualifier(JOB_NAME) JobDetail jobDetail) {
//triggerName代表一個trigger執行個體,會寫入資料庫,不能随便更改,改一次就會多一個trigger
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(TRIGGER_NAME).
這裡的觸發器和job進行一一綁定 withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)).forJob(jobDetail).build();
return cronTrigger;
}
@Bean(JOB_NAME)
public JobDetail getJob(){
return JobBuilder.newJob(HeartBeatJob.class). //jobname代表一個job會入庫,不能随便更改
withIdentity(JOB_NAME).storeDurably(true).build();
}
##*******Quartz提供兩種基本作業存儲類型
#******* 1、JDBC作業存儲持久化
#### Quartz配置:
## *****排程器的配置:
#排程器名稱
org.quartz.scheduler.instanceName= scadaClusteredScheduler
#ID設定為自動擷取 每一個必須不同 (所有排程器執行個體中是唯一的)如果使用叢集,instanceId必須唯一,設定成AUTO
org.quartz.scheduler.instanceId= AUTO
## *******jobStore 工作存儲配置:
#啟動jdbcJobStore而非RamJobStore:
spring.quartz.job-store-type=jdbc
#資料儲存方式為持久化spring.quartz.job-store-type
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
#StdJDBCDelegate說明支援叢集
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#quartz内部表的字首
org.quartz.jobStore.tablePrefix=QRTZ_
#是否加入叢集
org.quartz.jobStore.isClustered=true
# 分布式節點有效性檢查時間間隔,機關:毫秒
org.quartz.jobStore.clusterCheckinInterval=10000
#容許的最大作業延長時間,最大能忍受的觸發逾時時間,如果超過則認為“失誤”,不敢再記憶體中還是資料中都要配置
org.quartz.jobStore.misfireThreshold = 6000
## *******線程池配置:
#ThreadPool實作的類名
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
#線程數量
org.quartz.threadPool.threadCount=5
#線程優先級
org.quartz.threadPool.threadPriority=5
#配置為守護線程,設定後任務将不會執行
#org.quartz.threadPool.makeThreadsDaemons=true
#配置是否啟動自動加載資料庫内的定時任務,預設true
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
quartz叢集建表腳本
參考:https://blog.csdn.net/xiaohuaidan007/article/details/77485673?utm_source=blogxgwz4
--以下是quartz叢集表
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; --存放已觸發的觸發器
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; --存放暫停掉的觸發器
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; --排程器狀态,一個叢集就是一個執行個體
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; --簡單觸發器存儲
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; --cron觸發器資訊
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; --以blob形式存儲觸發器
DROP TABLE IF EXISTS QRTZ_TRIGGERS; --所有觸發器的總表
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; --job
DROP TABLE IF EXISTS QRTZ_CALENDARS; --calendar
--cron需要的幾張表:qrtz_triggers,qrtz_cron_triggers,qrtz_fired_triggers ,qrtz_job_details
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
二、Timer
1.代碼示範:
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask myTask = new TimerTask(){
@Override
public void run() {
System.out.println("Timer測試");
}
} ;
//目前時間延遲多久開始,間隔多久執行一次
// timer.schedule(myTask,1000L,1000L);
Calendar calendar = Calendar.getInstance();
calendar.set(2020,6,26,17,51,0);
//從什麼時間開始,間隔多久執行一次
//timer.schedule(myTask,calendar.getTime(),2000L);
//何時開始執行一次
//timer.schedule(myTask,calendar.getTime());
//從現在開始延遲多久執行一次
timer.schedule(myTask,3000L);
}
2.參考 https://blog.csdn.net/u014761700/article/details/79555768
3.原理和缺陷
(1)Timer其實就是最簡單的單線程任務,将線程中的任務執行内容的run方法進行調用
(2)timer缺陷很明顯,單線程,如果任務執行時間超過了間隔時間,就會導緻後面的任務因為阻塞等待而無法按時執行,此外單線程一旦報錯,線程就會被打斷,那麼後面的任務也就無法執行,是以timer隻适合執行比較簡單快速的任務
(3**)一般建議使用ScheduledThreadPoolExecutor替換timer建立簡單邏輯的定時任務**,因為線程池可做保證,使得任務并發執行