SpringBoot_SpringTask_Quartz
一、SpringTask和Quartz
1、两者都是用来任务调度的框架、比如需要每天定时清理垃圾数据
2、SpringTask
1、默认单线程同步执行
2、单个任务时,当前次的调度完成后,再执行下一次任务调度
3、多个任务时,一个任务执行完成后才会执行下一个任务。若需要任务能够并发执行,需手动设置线程池
4、触发方式:与Quartz的CronTrigger的表达式类似
5、可以使用注解标注定时任务
3、Quartz
1、默认多线程异步执行
2、单个任务时,在上一个调度未完成时,下一个调度时间到时,会另起一个线程开始新的调度。业务繁忙时,一个任务会有多个调度,可能导致数据处理异常。
3、多个任务时,任务之间没有直接影响,多任务执行的快慢取决于CPU的性能
4、触发方式一:SimpleTrigger:value=2000 每隔两秒触发
5、触发方式二:CronTrigger:value=”0 0 12 * * ?” 每天中午12点触发
6、需要在配置文件中实现配置Job
7、能被集群实例化,支持分布式部署
8、使用JobStoreCMT(JDBCJobStore的子类),Quartz 能参与JTA事务;Quartz 能管理JTA事务(开始和提交)在执行任务之间,这样,任务做的事就可以发生在JTA事务里。
4、两者的区别
1、实现,Task注解实现方式,比较简单。Quartz需要手动配置Jobs。
2、任务执行,Task默认单线程串行执行任务,多任务时若某个任务执行时间过长,后续任务会无法及时执行。Quartz采用多线程,无这个问题。
3、调度,Task采用顺序执行,若当前调度占用时间过长,下一个调度无法及时执行;Quartz采用异步,下一个调度时间到达时,会另一个线程执行调度,不会发生阻塞问题,但调度过多时可能导致数据处理异常
4、部署,Quartz可以采用集群方式,分布式部署到多台机器,分配执行定时任务
二、SpringTask的使用
1、导入jar包:spring-context.jar包就带这个功能、所以选择 web就可以使用了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、编写一个类,被Spring管理即可执行
import java.util.Date;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
@Component
public class TaskTools {
static int count=0;
@Scheduled( fixedRate = 5000 )
public void test001() {
System.out.println("无论上一次执行需要多少秒,我都会在5秒后执行:"+new Date().getSeconds());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Scheduled( fixedDelay = 5000 )
public void test002() {
System.out.println("上一次执行完毕后,再过5秒,我再执行:"+new Date().getSeconds());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//@Scheduled(cron = "0 0/1 * * * ? ")
public void test003(){
System.out.println("我会每隔1分钟执行一次");
}
//initialDelay 初始化延迟时间,也就是标识第一次延迟执行的时间,只能配合 fixedDelay 或 fixedRate 使用
//@Scheduled(initialDelay = 5000, fixedRate = 5000)
public void test004() {
System.out.println("第一次执行需要5秒后");
}
}
3、@Scheduled常用属性介绍
属性名 | 属性作用 |
---|---|
fixedRate | 上一次执行无论需要多少秒结束,我都会在5秒后执行 |
fixedDelay | 上一次执行完毕后,我再执行 |
cron | Cron表达式:在线生成https://cron.qqe2.com/ |
initialDelay | 初始化延迟时间,也就是标识第一次延迟执行的时间,只能配合 fixedDelay 或 fixedRate 使用 |
4、启动类添加注解
@SpringBootApplication
@EnableScheduling
public class Springboot004Application {
public static void main(String[] args) {
SpringApplication.run(Springboot004Application.class, args);
}
}
5、CronExpression表达式详解
https://www.jianshu.com/p/1defb0f22ed1
在线制作Cron表达式:https://www.bejson.com/othertools/cron/
格式为:{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}
cron表达式各占位符解释:
以下为{秒数}的案例 ==> 允许值范围: 0~59 ,不允许为空值,若值不合法,调度器将抛出SchedulerException异常
"*" 代表每隔1秒钟触发;
"," 代表在指定的秒数触发,比如"0,15,45"代表0秒、15秒和45秒时触发任务
"-" 代表在指定的范围内触发,比如"25-45"代表从25秒开始触发到45秒结束触发,每隔1秒触发1次
"/" 代表触发步进(step),"/"前面的值代表初始值(""等同"0"),后面的值代表偏移量,比如"0/20"或者"/20"代表从0秒钟开始,每隔20秒钟触发1次,即0秒触发1次,20秒触发1次,40秒触发1次;"5/20"代表5秒触发1次,25秒触发1次,45秒触发1次;"10-45/20"代表在[10,45]内步进20秒命中的时间点触发,即10秒触发1次,30秒触发1次
三、Quartz的使用
1、导入jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2、创建一个【被调度的类】
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class MyJob implements Job {
private void before() {
System.out.println("任务开始执行");
}
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
before();
System.out.println("开始:" + System.currentTimeMillis());
JobDataMap jdMap = context.getJobDetail().getJobDataMap(); //获得传递过来的参数
System.out.println(jdMap.get("key"));
System.out.println("结束:" + System.currentTimeMillis());
after();
}
private void after() {
System.out.println("任务开始执行");
}
}
3、创建一个调用【任务调度服务】
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/student")
public class MyController {
@Autowired
Scheduler scheduler;
@RequestMapping(value = "/index001")
public void testTask() throws SchedulerException {
JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("job2", "group2").build();
jobDetail.getJobDataMap().put("key", "张三"); // 给自定义任务传值
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 0/1 * * * ?");
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("job2", "group2")
.withSchedule(cronScheduleBuilder).build();
scheduler.scheduleJob(jobDetail, cronTrigger);
}
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("Trigger_HelloQuartz", "group1") // 定义name/group
// .startNow()//一旦加入scheduler,立即执行11
.startAt(new Date(System.currentTimeMillis() + 5000))// 5秒后执行
.withSchedule(SimpleScheduleBuilder.simpleSchedule() // 使用SimpleTrigger
.withIntervalInSeconds(2) // 每隔2秒执行一次
.withRepeatCount(1))// 重复1次,共计2次
// .repeatForever()) //一直执行,奔腾到老不停歇
.build();
}