springboot中定时任务的使用,有几种方式,亲测有效
一、使用注解方式@Scheduled
如图所有新建一个类,然后添加如图所示
在这里插入图片描述
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.time.LocalDateTime;
@Configuration // 主要用于标记配置类,兼备Component的效果。这个注解用的很多地方
@EnableScheduling // 定时任务的开启
public class SaticScheduleTask {
//定时任务
@Scheduled(cron = "0/5 * * * * ?")
//@Scheduled(fixedRate=5000) 这是另一种写法,毫秒计算
private void configureTasks() {
System.err.println("执行定时任务时间: " + LocalDateTime.now().toLocalTime());
}
}
启动执行打印结果如下所示
这种方式比较死板,修改配置后必须通过重启来执行,看自己需求吧。
简单解释下Cron表达式: spring自带的定时任务中正确的cron表达式只能是6个域,否则会抛出IllegalArgumentException提示:Cron expression must consist of 6 fields(cron表达式必须由6个域组成)。
常用表达式示例:
0/2 * * * * ? 表示每2秒 执行任务
0 0/2 * * * ? 表示每2分钟 执行任务
0 0 2 1 * ? 表示在每月的1日的凌晨2点调整任务
0 15 10 ? * MON-FRI 表示周一到周五每天上午10:15执行作业
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 12 ? * WED 表示每个星期三中午12点
0 0 12 * * ? 每天中午12点触发
0 15 10 ? * * 每天上午10:15触发
0 15 10 * * ? 每天上午10:15触发
0 15 10 * * ? 每天上午10:15触发
0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
0 15 10 ? * MON-WED,SAT 周一至周三和周六的上午10:15触发
0 15 10 15 * ? 每月15日上午10:15触发
0 15 10 L * ? 每月最后一日的上午10:15触发
0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发
二、实现SchedulingConfigurer接口
这种方式可以把定时的时间配置通过数据或者其它方式来进行修改,在定时任务执行体中,根据读取的配置进行任务执行。
例如我是从数据库获取的,如下图所示
import com.example.demo1.dao.PersonnelDao;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.thymeleaf.util.StringUtils;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Configuration // 主要用于标记配置类,兼备Component的效果
@EnableScheduling // 开启定时任务
public class DynamicScheduleTask implements SchedulingConfigurer {
@Resource
private PersonnelDao personneldao;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
// 任务内容(Runnable)
() -> System.out.println("执行动态定时任务: " + LocalDateTime.now().toLocalTime()),
// 设置执行周期(Trigger)
triggerContext -> {
// 从数据库获取Cron表达式参数
Map params = new HashMap();
params.put("cronId","1");
Map<String, Object> data = personneldao.selectCron(params);
String cron = String.valueOf(data.get("cron"));
// 校验,或者也可以添加其它校验。只要查出的能满足Cron表达式规则就行
if(StringUtils.isEmpty(cron)){
//抛异常或者给相应的提示,根据自己需求
}
//返回执行周期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
}
执行中没间隔5秒
现在我把数据库改成0/10也就是10秒
至此,第二种方式完成。
三、多线程定时任务,用异步注解就行处理
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.time.LocalDateTime;
//@Component注解用于对那些比较中立的类进行注释;
@Configuration
@EnableScheduling // 定时任务的开启注解
@EnableAsync // 开启异步 多线程
public class MultithreadScheduleTask {
//开启了多线程,该任务执行时间也不受其本身执行时间的限制,注意可能会出现重复操作导致数据异常。
@Async
@Scheduled(fixedDelay = 1000) //间隔1秒
public void first() throws InterruptedException {
//执行体
System.out.println("1号定时任务开始: " + LocalDateTime.now().toLocalTime() + "线程: " + Thread.currentThread().getName());
Thread.sleep(2000 * 10);
}
@Async
@Scheduled(fixedDelay = 2000)
public void second() {
//执行体
System.out.println("2号定时任务开始: " + LocalDateTime.now().toLocalTime() + "线程: " + Thread.currentThread().getName());
}
}
启动执行后如下
从执行结果看,亲测有效,且两者互不干扰。
大家一起学习哈哈