网站首页 > 开源技术 正文
定时任务在我们项目开发中也是很重要的,对于某些场景必须要用定时任务 ,如定时发送邮件啊,定时统计数据等,这篇文章主要讲讲项目中实现定时任务的几种方式。
一、基于注解
这种方式很简单,主要就是先@EnableScheduling开启定时任务功能,然后在相应的方法上添加@Scheduled()中间写上相应的cron表达式即可。示例如下:
schedule.ScheduleTask:
java复制代码import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
@EnableScheduling //开启定时任务
public class ScheduleTask {
@Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
public void testScheduleTask() {
System.out.println("执行定时任务" + LocalDateTime.now());
}
}
Cron表达式参数参考:
- 秒(0~59) 例如0/5表示每5秒
- 分(0~59)
- 时(0~23)
- 日(0~31)的某天,需计算
- 月(0~11)
- 周几( 可填1-7 或 SUN/MON/TUE/WED/THU/FRI/SAT)
建议:直接在线生成Cron表达式比较方便:www.matools.com/cron/
@Scheduled:除了支持灵活的参数表达式cron之外,还支持 fixedDelay,fixedRate,initialDelay 这些延时性的操作。
启动测试就实现了基本的定时任务功能,但是如果我们修改了cron表达式,需要重启整个应用才能生效,不是很方便。想要实现修改cron表达式就生效就需要用到接口的方式来实现定时任务。
二、基于接口
接口的方式是我们把定时任务的信息放在数据库中,程序从数据库去拉取定时任务的信息如cron表达式来实现实时修改生效等功能。
1. 首先在数据库中创建一张用来记录定时任务的表
sql复制代码CREATE TABLE `scheduled` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(255) NULL,
`cron` varchar(255) NULL,
PRIMARY KEY (`id`)
)
INSERT INTO `mydb`.`scheduled` (`id`, `name`, `cron`) VALUES (1, '定时任务1', '0/6 * * * * ?')
2. 在项目中引入mabatis-plus和mysql相应的依赖包
xml复制代码<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
3. 在application.yml中进行连接数据库相应配置
yml复制代码spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb?characterEncoding=utf-8&serverTimeZone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
4. 定义查询cron表达式的mapper
mapper.CronMapper:
java复制代码import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface CronMapper {
@Select("select cron from scheduled where id=#{id}")
String getCron(Long id);
}
5. 实现定时任务
java复制代码import com.jk.mapper.CronMapper;
import org.springframework.beans.factory.annotation.Autowired;
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.springframework.stereotype.Component;
@Component
@EnableScheduling //开启定时任务
public class ScheduleTask implements SchedulingConfigurer {
@Autowired
private CronMapper cronMapper;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
//添加任务内容
() -> process(),
//设置执行的周期
triggerContext -> {
//查询cron表达式
String cron = cronMapper.getCron(1L);
if (cron.isEmpty()) {
System.out.println("cron is null");
}
return new CronTrigger(cron).nextExecutionTime(triggerContext);
});
}
private void process() {
System.out.println("基于接口的定时任务");
}
}
这种方式需要去实现SchedulingConfigurer接口并重写configureTasks方法,然后设置任务内容和执行周期等,启动测试就实现了基于接口的定时任务,此时我们改动数据库里的cron表达式也会实时生效
三、多线程定时任务
但上面的方法定义的定时任务会有个问题,就是如果我一个定时任务里面执行了复杂逻辑,导致本身执行花的时间就已经超过了定时任务间隔的时间怎么办呢?这时候定时任务的执行就会出现一定的问题,具体如下,我用线程睡眠的方式模拟处理复杂逻辑
java复制代码import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
@EnableScheduling //开启定时任务
public class ScheduleTask {
@Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
public void testScheduleTask1() throws InterruptedException {
System.out.println("执行定时任务1 " + LocalDateTime.now());
Thread.sleep(10 * 1000);
}
@Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
public void testScheduleTask2() {
System.out.println("执行定时任务2 " + LocalDateTime.now());
}
}
可以看到两个任务的执行时间都被影响了,和我们设置的5秒不对应。此时就可以使用多线程定时任务,对多线程的使用不了解的可以看我的另一篇文章 SpringBoot 中异步任务实现及自定义线程池执行异步任务
java复制代码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 org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
@EnableScheduling //开启定时任务
@EnableAsync //开启多线程
public class ScheduleTask {
@Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
@Async
public void testScheduleTask1() throws InterruptedException {
System.out.println("执行定时任务1 " + LocalDateTime.now());
Thread.sleep(10 * 1000);
}
@Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
@Async
public void testScheduleTask2() {
System.out.println("执行定时任务2 " + LocalDateTime.now());
}
}
这样多线程的定时任务就实现了,每个定时任务之间不会互相影响,定时任务执行时间太长也不会影响。
作者:JK凯
链接:https://juejin.cn/post/7236217091966402618
猜你喜欢
- 2024-10-27 三十七,Web渗透提高班之hack the box在线靶场注册及入门知识
- 2024-10-27 超棒的MD5加密工具(md5加密技术)
- 2024-10-27 任务调度框架 Quartz 用法指南「超详细」
- 2024-10-27 免费的代码比较工具(代码比较器)
- 2024-07-20 吐血推荐!史上最实用的在线工具网站,每一个强大到你无法想象!
- 2024-07-20 教你制作彩色、带LOGO的二维码(教你制作彩色,带logo的二维码怎么做)
- 2024-07-20 推荐10个免费在线神器,让你的工作效率大大提升
- 2024-07-20 我是如何提取人民币中的高逼格配色的?
- 2024-07-20 系统任务指令(定时任务执行工具)--cron
- 2024-07-20 卡通头像制作工具(卡通头像制作工具下载)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- jdk (81)
- putty (66)
- rufus (78)
- 内网穿透 (89)
- okhttp (70)
- powertoys (74)
- windowsterminal (81)
- netcat (65)
- ghostscript (65)
- veracrypt (65)
- asp.netcore (70)
- wrk (67)
- aspose.words (80)
- itk (80)
- ajaxfileupload.js (66)
- sqlhelper (67)
- express.js (67)
- phpmailer (67)
- xjar (70)
- redisclient (78)
- wakeonlan (66)
- tinygo (85)
- startbbs (72)
- webftp (82)
- vsvim (79)
本文暂时没有评论,来添加一个吧(●'◡'●)