通过定时任务,可以方便实现一些现实业务,如预约挂号系统,可以实现每天8点对当天有预约就医的用户进行短信提醒就诊。而 SpringBoot 就可以方便地实现这种定时任务。
SpringBoot 定时任务的实现有三种方式:
- 基于注解
@Scheduled
默认的静态单线程 - 基于注解
@Scheduled
、@Async
设定多线程 - 基于接口 SchedulingConfigurer 实现动态定时任务
一、基于注解的单线程定时任务
实现步骤:创建配置类,使用 @EnableScheduling
开启定时任务,并在定时任务的具体方法上使用 @Scheduled
来配置方法的定时规则。
@Component //也可以使用 @Configuration 来标记,包含@Component的效果
@EnableScheduling //开启定时任务
public class ScheduledTask {
@Autowired
private Service service;
@Scheduled(cron = "0 0 1 * * ?") //编写cron表达式,效果为每天8点执行
public void task1() {
service.doSth();
}
}
@Scheduled 可以支持灵活的参数表达式cron,cron 表达式无需特别的记忆,通过 https://www.matools.com/cron/ 直接生成即可。
该注解还支持延时操作,填写相应的毫秒数即可。例如:
- fixedDelay 设置上一次任务执行结束到下一次执行开始的间隔时间;
(当前一个任务执行完毕后,等待固定的时间间隔,再执行下一次任务) - fixedRate 设置上一次任务执行结束到下一次执行开始的间隔时间;
(不管前一个任务执行是否执行完毕,总是匀速执行新任务) - initialDelay 设置首次任务执行的延迟时间。
二、基于注解的多线程定时任务
创建多线程定时任务,需要使用 EnableAsync
开启多线程,并在需要启动多线程的方法上标注 @Async
。
@Component
@EnableScheduling //开启定时任务
@EnableAsync //开启多线程
public class MultithreadScheduleTask {
@Async
@Scheduled(fixedDelay = 3000) //间隔3秒
public void task1() throws InterruptedException {
System.out.println("任务一开始运行..."+Thread.currentThread().getName()+ LocalDateTime.now().toLocalTime());
Thread.sleep(10000); //模拟线程睡眠
}
@Async
@Scheduled(fixedDelay = 5000) //间隔5秒
public void task2() {
System.out.println("任务二开始运行..."+Thread.currentThread().getName()+ LocalDateTime.now().toLocalTime());
}
}
成功实现,两个定时任务互不影响:
三、基于接口的动态定时任务
基于注解能非常方便的创建定时任务,但是需要更改定时规则,需要重启 SpringBoot 应用才能生效。这对于一些场景是非常有弊的,而基于接口 SchedulingConfigurer 的方式创建动态定时任务,可以解决这个问题,利用数据库来达到实施生效的效果。
实现步骤:
第一步,在数据库中新建一张表 cron ,sql 语句如下:
CREATE TABLE `cron` (
`cron_id` varchar(30) NOT NULL PRIMARY KEY,
`cron` varchar(30) NOT NULL
);
第二步,创建 mapper ,用于取出数据表中存放的 cron 表达式。
@Mapper
public interface CronMapper {
@Select("select cron from cron limit 1")
String getCron();
}
第三步,在需要定时执行的任务所在的类中实现 Runnable 接口。
public class UserService implements Runnable{
@Override
public void run() {
System.out.println("每隔10秒提示用户....");
}
}
第四步,创建定时任务配置类,注入 cronMapper,取出 cron 表达式并用接口方法注册定时任务。
@Configuration
@EnableScheduling //开启定时任务
public class DynamicScheduledTask implements SchedulingConfigurer {
@Autowired
private CronMapper cronMapper;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
//获取cron表达式
String cron = cronMapper.getCron();
if(StringUtils.isEmpty(cron)){
throw new RuntimeException("数据库获取Cron表达式为null...");
}
//注册定时任务(参数1:添加任务内容RunnableTask;参数2:添加执行周期TriggerContext)
scheduledTaskRegistrar.addCronTask(new UserService(),cron);
}
}
成功实现:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/93529.html