一、静态定时任务
静态定时任务主要是通过 @Scheduled来实现的,我们先讲解一下这个注解里面的属性。
属性 | 说明 |
---|---|
cron | 使用cron表达式来指定该方法的执行周期 |
zone | 时区,一般不用管 |
fixedDelay | 指定多少时间内执行一次,如果上一次定时任务没有执行完,则会等待执行完。 |
fixedDelayString | 和fixedDelay意思一样,格式是字符串类型 |
fixedRate | 指定多少时间内执行一次,如果上一次定时任务没有执行完,则不会等待。 |
fixedRateString | 和fixedRate意思一样,格式是字符串类型 |
initialDelay | 项目启动完后等待多久后再立即执行 |
initialDelayString | 和initialDelay意思一样,格式是字符串类型 |
timeUnit | 时间单位,默认毫秒 |
注意:除了zone和timeUnit,其他属性只能存在一个,不推荐使用fixedRate因为会产生定时任务重复执行问题。
1、启动类加注解
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
2、编写定时任务类
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class Test {
@Scheduled(cron = "0/5 * * * * ?")
//也可以写成多少毫秒执行一次
//@Scheduled(fixedRate = 5000)
public void test(){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间"+sdf.format(new Date()));
}
}
cron表达式在线生成地址:https://cron.qqe2.com/
上面的这种定时任务有很多弊端:比如,修改了cron表达式需要重启,无法停止、修改添加和删除下面我就来讲一下SpringBoot的动态定时任务
二、动态定时任务
1、启动类加注解
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
2、编写任务管理类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
/**
* @author hq
* @date: 2022/5/19 13 57 10
*/
@Component
public class JobManager {
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
Map<String, ScheduledFuture<?>> map = new HashMap<>();
/**
* 停止定时任务
*/
public int stopTask(String jobName) {
ScheduledFuture<?> future = map.get(jobName);
if (future != null) {
future.cancel(true);
return 1;
}
return 0;
}
/**
* 添加定时任务
*
* @param jobName 任务名
* @param runnable 执行的类
* @param cron cron表达式
*/
public void addTask(String jobName, Runnable runnable, String cron) {
ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(runnable, new CronTrigger(cron));
map.put(jobName, future);
}
/**
* 删除定时任务
*
* @param jobName
*/
public int deleteTask(String jobName) {
ScheduledFuture<?> future = map.get(jobName);
if (future != null) {
future.cancel(true);
map.remove(jobName);
return 1;
}
return 0;
}
/**
* 修改定时任务
*
* @param cron
*/
public int updateTask(String jobName,Runnable runnable,String cron) {
ScheduledFuture<?> future = map.get(jobName);
if (future != null) {
future.cancel(true);
//重新设置时间格式需符合cron表达式
future = threadPoolTaskScheduler.schedule(runnable, new CronTrigger(cron));
map.put(jobName, future);
return 1;
}
return 0;
}
}
3、编写需要执行的类
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyRunnable1 implements Runnable{
@Override
public void run() {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("任务当前时间"+sdf.format(new Date()));
}
}
注:必须要实现Runnable接口
4、编写测试类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Test {
@Autowired
private JobManager jobManager;
/**
* 添加定时任务
* @param jobName 任务名
* @param path 需要执行的类的路径(需要实现Runnable接口)
* @param cron cron表达式
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
*/
@RequestMapping("/addTask")
public void addTask(String jobName, String path, String cron) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName(path);
jobManager.addTask(jobName, (Runnable) clazz.newInstance(), cron);
}
/**
* 删除任务
*
* @param jobName
*/
@DeleteMapping("deleteTask")
public void deleteTask(String jobName) {
jobManager.deleteTask(jobName);
}
/**
* 修改任务
* @param jobName 任务名
* @param path 需要执行的类的路径(需要实现Runnable接口)
* @param cron cron表达式
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
*/
@GetMapping("/updateTask")
public void updateTask(String jobName,String path,String cron) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName(path);
jobManager.updateTask(jobName,(Runnable) clazz.newInstance(), cron);
}
/**
* 停止定时任务
**/
@RequestMapping("/stopTask")
public void stopTask(String jobName) {
jobManager.stopTask(jobName);
}
}
虽然这种方式可以实现定时任务的增删改查,但功能还是有些不全,远不如专业的定时任务框架功能强大 ,比如xxl-job和Quartz。