【总结】spring定时任务
1.spring - @schedule定时任务器
1.1.实现
1.引入依赖
spring3.0后自带的定时任务器,所以只需引入spring依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
2.定时任务类
@Component
public class ScheduleDemo {
@Scheduled(cron = "0/2 * * * * ?")
public void scheduleMethod(){
System.out.println("定时器被触发" + new Date());
}
}
3.启动类加@EnableScheduling注解
4.效果.每两秒打印一次

1.2.cron表达式
1.cron表达式是一个字符串,分为6或7个域,每一个域代标一个含义
2.cron有如下两种语法格式:
(1)秒 分 时 日 月 星期 年
(2)秒 分 时 日 月 星期
推荐使用6个域的表达式(有的定时任务器要求为6个域,否则会出错)
(注意:星期的1表示星期日)
3.各字段的含义

(1):表示匹配该域的任意值。假如在Minutes域使用, 即表示每分钟都会触发事件。
(2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用,如果使用表示不管星期几都会触发,实际上并不是这样
(3)-:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次
(4),:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。
(5)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三
(6)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次
2.spring - SchedulingConfigurer定时任务器
2.1 SchedulingConfigurer介绍
@Schedule注解的一个缺点就是其定时时间不能动态更改,它适用于具有固定任务周期的任务,若要修改任务执行周期,只能走“停服务→修改任务执行周期→重启服务”这条路。
而基于 SchedulingConfigurer 接口方式可以做到。SchedulingConfigurer 接口可以实现在@Configuration 类上,同时不要忘了,还需要@EnableScheduling 注解的支持
2.2 SchedulingConfigurer实现
1.创建数据库表
CREATE TABLE `trip_job_lock` (
`job_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '定时任务名称',
`is_lock` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否开启任务 1-开启,0-关闭',
`job_cron` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时任务执行时间间隔',
`job_desc` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时任务中午描述',
PRIMARY KEY (`job_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务配置表' ROW_FORMAT = Dynamic;
INSERT INTO `trip_job_lock` VALUES ('1', NULL, '0/5 * * * * ?', NULL);
2.SchedulingConfigurer接口
实现SchedulingConfigurer接口重写configureTasks方法
@Component
public class SchedulerTask implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
this.registrar = scheduledTaskRegistrar;
taskTriggerModels = new ArrayList<>();
logger.info("初始化定时任务配置");
//"update OrderTask set IsRunning = 0 where IsExecute = 1 and Isdel = 0"
orderTaskMapper.init();
scheduledTaskRegistrar.addTriggerTask(SyncCompeteAgentInfoByCaChange(), getTrigger(TaskEnum.SyncCompeteAgentInfoByCaChange.getTaskCode()));
//用于controller里,重新启动或更新任务
List<TriggerTask> tasks = scheduledTaskRegistrar.getTriggerTaskList();
if (tasks != null && tasks.size() > 0) {
for (TriggerTask task : tasks) {
Optional<TaskTriggerModel> optional = taskTriggerModels.stream().filter(o -> o.getTrigger() == task.getTrigger()).findFirst();
if (optional.isPresent()) {
optional.get().setRunnable(task.getRunnable());
}
}
}
/**
* 从数据库中获取触发时间
*/
private Trigger getTrigger(String taskCode) {
Trigger trigger = new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
OrderTask task = orderTaskMapper.selectByTaskCode(taskCode);
int isContinue = 1;
String[] codeArry = {"2", "3", "6"};
if ("uat".equals(proAction) && !Arrays.asList(codeArry).contains(taskCode)) {
isContinue = 0;
}
if (task != null && isContinue == 1) {
logger.info("任务编码:" + taskCode + " cron: " + task.getCron());
// 触发器
CronTrigger trigger = new CronTrigger(task.getCron());
return trigger.nextExecutionTime(triggerContext);
} else {
logger.info("定时任务初始化失败,任务编码:{},请检查数据库中的任务状态。", taskCode);
return null;
}
}
};
TaskTriggerModel model = new TaskTriggerModel();
model.setTaskCode(taskCode);
model.setTrigger(trigger);
taskTriggerModels.add(model);
return trigger;
}
}
3.schedule定时任务原理
JUC 包中的 Executor 架构带来了线程的创建与执行的分离。Executor 的继承者 ExecutorService 下面衍生出了两个重要的实现类,他们分别是
ThreadPoolExecutor 线程池
ScheduledThreadPoolExecutor 支持周期性任务的线程池
通过 ThreadPoolExecutor 可以实现各式各样的自定义线程池,而 ScheduledThreadPoolExecutor 类则在自定义线程池的基础上增加了周期性执行任务的功能

浙公网安备 33010602011771号