定时任务
作者:互联网
定时任务的实现
-
timer
-
quartz
-
spring的scheduled
quartz
首先我们来看看quartz的使用。
使用首先要明白quartz的三个核心概念:
- Job(作业): 表示一个工作,要执行的具体内容。
- trigger(触发器): 什么时间做
- scheduler(调度器): 什么时间做什么任务
- jobDetail: 任务详细描述
基本使用
示例: 每隔5秒中提醒一次该开会了
使用步骤:
- 引入依赖
- 编写job
- 创建jobDetail描述任务,创建触发器,创建调度器,通过调度器调度任务
依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
示例
package demo;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class RemindJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String remindTime = new SimpleDateFormat("yy-MM-dd HH:mm:ss:SSS").format(new Date());
System.out.println("提醒时间:" + remindTime + ", 该开会了...");
}
}
调度器和触发器
package demo;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.concurrent.TimeUnit;
public class SchedulerDemo {
public static void main(String[] args) throws SchedulerException, InterruptedException {
// 1、创建调度器Scheduler
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
// 2、创建 JobDetail 实例,并与 RemindJob 类绑定(Job执行内容)
JobDetail jobDetail = JobBuilder.newJob(RemindJob.class)
.withIdentity("remindJob", "group1").build();
// 3、构建 Trigger 实例,每隔5s执行一次
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("trigger1", "triggerGroup1")
.startNow()//立即生效
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(5) //每隔5s执行一次
.repeatForever()) //一直执行
.build();
//4、执行
scheduler.scheduleJob(jobDetail, trigger);
System.out.println("--------scheduler start ! ------------");
scheduler.start();
//睡眠
TimeUnit.MINUTES.sleep(1);
scheduler.shutdown();
System.out.println("--------scheduler shutdown ! ------------");
}
}
cron触发器
CronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用。CroTrigger是基于Cron表达式的,先了解下Cron表达式:
由7个子表达式组成字符串的,格式如下:
[秒] [分] [小时] [日] [月] [周] [年]
序号 | 说明 | 是否必填 | 允许填写的值 | 允许的通配符 |
---|---|---|---|---|
1 | 秒 | 是 | 0-59 | , - * / |
2 | 分 | 是 | 0-59 | , - * / |
3 | 时 | 是 | 0-23 | , - * / |
4 | 日 | 是 | 1-31 | , - * ? / L W |
5 | 月 | 是 | 1-12或JAN-DEC | , - * / |
6 | 周 | 是 | 1-7或SUN-SAT | , - * ? / L W |
7 | 年 | 否 | empty 或1970-2099 | , - * / |
通配符表示的意思:
* 表示每x(秒,分,天,月,日,周几)的意思
0/5 * * * * ? : 从0秒开始,每增加5秒执行一次
0 0/5 * * * ? : 从0秒开始,每增加5分钟执行一次
5,8,12 * * * * ?: ,表示一个列表,表示在每一分钟里面的第5秒,第8秒,第12秒各执行一次
0 10 8,10,13 * * ? : 在8点,10点,13点的10分的时候,各执行一次
0 10 8-12 * * ?: -表示多少到多少之间,在8点到12的的每小时的第10分钟的时候执行任务
?: 只能出现在表示日期或值星期几的位置
W: workday(工作日)
L: 最后一天,或最后一周的周几
#: 表示第几周的意思
// 3、构建 Trigger 实例,每隔5s执行一次
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("trigger1", "triggerGroup1")
.startNow()//立即生效
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
.build();
和 spring boot 整合
- 引入 spring boot 整合quartz的依赖
- 写任务(继承 QuartzJobBean 抽象类)
- 配置 jobDetail和trigger对象
- 启动springboot项目
任务是继承 QuartzJobBean 抽象类
public class QuartzJob1 extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String remindTime = new SimpleDateFormat("yy-MM-dd HH:mm:ss:SSS").format(new Date());
System.out.println("提醒时间:" + remindTime + ", 该开会了...");
}
}
创建配置类
@Configuration
public class QuartzConfig {
@Bean
public JobDetail jobDetail1(){
return JobBuilder.newJob(QuartzJob1.class).storeDurably().build();
}
@Bean
public Trigger trigger1(){
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1) //每一秒执行一次
.repeatForever(); //永久重复,一直执行下去
return TriggerBuilder.newTrigger()
.forJob(jobDetail1())
.withSchedule(scheduleBuilder)
.build();
}
/*
@Bean(name = "jobDetail")
public MethodInvokingJobDetailFactoryBean detailFactoryBean(TimingTask task) {
// ScheduleTask为需要执行的任务
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
/*
* 是否并发执行
* 例如每3s执行一次任务,但是当前任务还没有执行完,就已经过了3s了.
* 如果此处为true,则下一个任务会bing执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行
*/
jobDetail.setConcurrent(true);
jobDetail.setName("scheduler");// 设置任务的名字
jobDetail.setGroup("scheduler_group");// 设置任务的分组,这些属性都可以存储在数据库中,在多任务的时候使用
/*
* 这两行代码表示执行task对象中的scheduleTest方法。定时执行的逻辑都在scheduleTest。
*/
jobDetail.setTargetObject(task);
jobDetail.setTargetMethod("start");
return jobDetail;
}
@Bean
public JobDetailFactoryBean jobDetail(){
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setJobClass(HiJob.class);
jobDetailFactoryBean.setBeanName("hiJob");
jobDetailFactoryBean.setGroup("jobGroup");
jobDetailFactoryBean.setDurability(true);
return jobDetailFactoryBean;
}
@Bean
public CronTriggerFactoryBean cronTrigger(JobDetailFactoryBean jobDetailFactoryBean){
CronTriggerFactoryBean triggerFactoryBean = new CronTriggerFactoryBean();
triggerFactoryBean.setCronExpression("0/5 * * * * ?");
triggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
return triggerFactoryBean;
}
*/
}
spring的scheduled
在SpringBoot使用Spring Schedule非常简单,因为SpringBoot自身的starter中已经集成了Schedule,而不需要我们做更多的处理。
使用@EnableScheduling注解开启定时功能,该注解可以使用在启动类上,也可以注解于定时任务的类上。然后使用@Scheduled注解配合其参数完成定时任务。
依赖
org.springframework:spring-context 包
- 在启动类上面使用 @EnableScheduling 开启定时任务
@SpringBootApplication
@EnableScheduling
public class SpringBootQuartzDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootQuartzDemoApplication.class, args);
}
}
固定延时任务频率任务
- 在要定时运行的方法上面加注解 @Scheduled
@Component
public class ScheduledComponet {
private static Logger LOGGER = LoggerFactory.getLogger(ScheduledComponet.class) ;
@Scheduled(fixedDelay = 5000)
public void testSheduled() throws InterruptedException {
TimeUnit.SECONDS.sleep(6);
LOGGER.info("定时任务1: 线程: [ {} ],[ {} ]",Thread.currentThread().getName(),new Date());
}
@Scheduled(fixedRate= 3000)
public void testSheduled2() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
LOGGER.info("定时任务2: 线程: [ {} ],[ {} ]",Thread.currentThread().getName(),new Date());
}
@Scheduled(cron = "0/5 * * ? * *")
public void testSheduled3() throws InterruptedException {
TimeUnit.SECONDS.sleep(8);
LOGGER.info("定时任务3: 线程: [ {} ],[ {} ]",Thread.currentThread().getName(),new Date());
}
}
注意
多个 @Scheduled 注解的方法是在一个线程中执行的,如果运行比较耗时,会阻塞其他任务的执行,使用 @Async 和 @EnableAsync 开启异步任务,可以解决,会使用异步任务线程池来运行. spring 的 cron 表达式中不允许出现字母.
@SpringBootApplication
@EnableScheduling
@EnableAsync // 开启异步
public class SpringBootQuartzDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootQuartzDemoApplication.class, args);
}
}
@Scheduled(fixedDelay = 5000)
@Async // 方法异步执行
public void testSheduled() throws InterruptedException {
TimeUnit.SECONDS.sleep(6);
LOGGER.info("定时任务1: 线程: [ {} ],[ {} ]",Thread.currentThread().getName(),new Date());
}
标签:public,任务,new,定时,执行,class,jobDetail 来源: https://www.cnblogs.com/liuqi0517/p/16133323.html