❤ 静态任务
[!quote] 静态任务 静态任务 是在应用启动时就被加载和注册的定时任务,调度时间在应用启动时就被计算。它们是基于配置文件或代码中的
@Scheduled注解声明的
java
@Scheduled(cron="0 0 2 * * ?") //每天凌晨2点执行
public void doStaticTask() {
// 执行静态定时任务的代码
}💛 操作步骤
- 在类上加入
@EnableScheduling,开启定时任务
java
@EnableScheduling
public class ChatBotSchedule {……}- 使用
@Scheduled,对任务设置执行时间。有三种配置执行时间的方式:cron 表达式fixedRate自上一次执行开始之后多长时间执行【单位是毫秒】fixedRateString与fixedRate相同,但是支持占位符fixedDelay自上一次执行结束之后多长时间执行【单位是毫秒】fixedDelayStringinitialDelay首次执行要延迟多长时间【单位毫秒】initialDelayString
java
@Scheduled(cron = "0/20 * * * * ?")
@Scheduled(fixedRate = 1 * 60 * 1000)
// 配置文件中
interval=2000
@Scheduled(fixedRateStirng="${interval}")
public void RunSchedule() {……}💛 @Scheduled
💙 Cron 表达式
cron= "秒 分 时 日 月 周几"
`周` 和 `日` 不能同时存在【一个设置了,另一个就要设置为 `?` 】
- 取值
秒0-59分0-59时0-23日1-31月1-12周0-7【0/7 是 周日,1-6 是周一到周六】
- 通配符
#每月的第几个周几【比如1#2,表示每月的第 2 个星期天】【==只用在周==】L每月的最后一个什么【比如,在日上3L表示这个月的倒数第三天,周上3L表示这个月的最后一个周四【==只用在周,或日==】【Spring 中不支持】*所有值,表示每秒,每月,每日?不指定值【比如已经设置了每日,那具体周几就不用设置了,那么就设为?】-表示区间【比如在周上设置3-5,就表示周三到周五都会执行】,多个并列【比如日的2,13,14,就是 2 号,13 号,14 号都会执行】/间隔【比如秒的2/3,从第 2 秒开始,每三秒触发一次】
java
0/2 * * * * ? 从第 0 秒开始,每 2 秒触发
0 0/5 14 * * ? 在每天下午 2 点到下午 2:55 期间的每5分钟触发【2 点会触发,2:55 也会触发】
0 15 10 ? * 6#3 每月的第三个星期五上午 10:15 触发
0 0 2 1 * ? 每月的 1 号,凌晨 2 点触发
0 * 14 * * ? 每天下午 2 点到下午 2:59 的每 1 分钟触发
0 0-5 14 * * ? 每天下午 2 点到下午 2:05 的每 1 分钟触发💙 fixedRate
fixedRate 的时间单位是毫秒
java
@Scheduled(fixedRate = 6300000) // 1h 45min💙 fixedRateString
java
// 配置文件
interval=2000
// 注解引用
@Scheduled(fixedRateStirng="${interval}")💙 initialDelay
java
// 系统启动之后立马会执行一次
@Scheduled(fixedRate = 6300000, initialDelay = 0)💛 定时调度异步线程池
[!quote] 定时调度异步线程池 定时调度异步线程池 既用来调度任务,也用来异步执行任务
- 如果不额外创建线程池,那所有的定时任务都会使用默认的线程池(大小为 1)
- 配置好的线程池,在被
@Scheduled自动应用- 当任务开始调度时,会把任务放进队列中,到达指定时间后,再从使用线程来执行该任务
java
/**
* 异步定时任务配置类
*/
@EnableScheduling
@Configuration
public class AsyncSchedulingConfig {
@Bean(name = "myScheduledThreadPool")
public ThreadPoolTaskScheduler myScheduledThreadPool() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(20); // 设置线程池大小
scheduler.setThreadNamePrefix("MyScheduledThreadPool - ");
scheduler.initialize();
return scheduler;
}
}❤ 动态任务
动态任务是在运行时动态添加和移除的定时任务,而不需要重新启动应用
💛 动态 Cron
java
@Component
public class DynamicTaskScheduler {
private ScheduledFuture<?> currentTask;
@Resource
private ThreadPoolTaskScheduler scheduler;
public void scheduleTask(String cron) {
// 如果有正在运行的任务,取消它
if (currentTask != null && !currentTask.isCancelled()) {
currentTask.cancel(true);
}
// 调度新的任务
currentTask = scheduler.schedule(() -> {
// 执行动态定时任务的代码
}, new CronTrigger(cron));
}
}💛 动态延时任务
ScheduledExecutorService用于管理定时任务的执行ScheduledFuture持有定时任务的执行状态和结果,用于取消任务,或检查任务是否完成,在调用 scheduler.schedule() 时立即生成isCancelled- false 任务正常进行,结束,执行中,执行报错
- true 只有当我们手动结束任务,才会返回
cancel(Boolean)- 传 true - 会中断正在执行的任务
- 传 false - 不会中断正在执行的任务,但会取消计划任务(后续不再执行)
在开启调度任务时,不会占用线程,只有在延时结束实际执行时才会占用线程,任务执行完毕,立马释放线程资源
java
/**
* 工时审批通知定时任务
*/
@Configuration
public class WHApprovalNotifyTask {
// 这里要提前定义好一个动态线程池
@Resource
private ThreadPoolTaskScheduler taskScheduler;
private ScheduledFuture<?> scheduledFuture;
/** 开启定时任务,有人登记工时,就调用该方法 */
public void scheduleTask(Integer delay) {
// 任务在delay小时后执行
scheduledFuture = taskScheduler.schedule(
() -> {
// 判断取消任务
if (scheduledFuture != null) scheduledFuture.cancel(false);
// 执行任务
notifyByUserIds();
},
Instant.now().plus(delay, ChronoUnit.HOURS)
);
}
}