玩转springboot2.x之整合定时任务篇

1 springboot 默认的定时任务处理

查看官方文档:http://spring.io/guides/gs/scheduling-tasks/ 我们这里将根据官方文档进行讲解如何使用。

使用spirngboot自带的任务调度拢共需要2步

1 启动类上声明 @EnableScheduling

2 spring bean 方法上声明 @Scheduled 并在注解中指定启动的规则

直接上代码

package cn.lijunkui;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class SpringbootlearnApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringbootlearnApplication.class, args);
	}
}
package cn.lijunkui.task.own;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
 *
 * @author lijunkui
 *
 */
@Component
public class SchedulerTask {
	
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	//固定的时间执行 也就是 5秒执行一次
    @Scheduled(fixedRate = 5000)
    public void reportCurrentTimeFixedRate() {
    	try {
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        log.info("reportCurrentTimeFixedRate The time is now {}", dateFormat.format(new Date()));
    }
}

测试效果

fixedRate:任务执行的时间是3秒 设置任务时间间隔5秒 实际按每5秒执行一次

fixedRate: 任务执行的时间是6秒 设置任务时间间隔5秒 实际按每6秒执行一次

 

接下俩我们重点说一下 Scheduled 注解 的经常使用参数设置项

fixedRate :固定的时间执行 也就是 多少秒执行一次。 这个我们上面的代码已经介绍完毕。

fixedDelay:执行完毕后再过5秒后执行

initialDelay:启动后延迟多少秒后执行 不能单独使用。

接下俩看看fixedDelay 和 initialDelay 设置项的demo案例:

package cn.lijunkui;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

import cn.lijunkui.task.own.SchedulerTask;

@SpringBootApplication
@EnableScheduling
public class SpringbootlearnApplication {
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); 
	public static void main(String[] args) {
		SpringApplication.run(SpringbootlearnApplication.class, args);
		 log.info("reportCurrentTimeInitialDelay fixedRate The time is start {}", dateFormat.format(new Date()));
	}
}
package cn.lijunkui.task.own;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
 * 
 * @author jrrry
 *
 */
@Component
public class SchedulerTask {
	
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    @Scheduled(initialDelay=0, fixedDelay=5000)
    public void reportCurrentTimeInitialDelay() {
    	try {
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        log.info("reportCurrentTimeInitialDelay fixedRate The time is now {}", dateFormat.format(new Date()));
    }
	
}

测试结果:

fixedDelay:任务执行的时间是3秒 设置任务时间间隔5秒 实际按每8秒执行一次

fixedDelay:任务执行的时间是6秒 设置任务时间间隔5秒 实际按每11秒执行一次 

 

同时 Scheduled 还支持 Cron 表达式方式

package cn.lijunkui.task.own;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class SchedulerTaskForCron {
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	/**
	 * 每天的14:00 执行一次
	 */
	@Scheduled(cron="0 0 14 * * ?")
	private void cron() {
		 log.info("cron The time is now {}", dateFormat.format(new Date()));
	}
	
	/**
	 * 每5秒执行一次
	 */
	@Scheduled(cron="0/5 * * * * ?")
	private void cron2() {
		try {
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.info("cron2 The time is now {}", dateFormat.format(new Date()));
	}
}

测试结果:

任务执行的时间是3秒 设置任务时间间隔5秒 实际按每5秒执行一次

任务执行的时间是6秒 设置任务时间间隔5秒 实际按每11秒执行一次 

 

关于cron使用规则 网上有很多在线生成工具 例如:http://www.bejson.com/othertools/cron/

2 springboot 使用JDK 定时任务处理

2.1 Timer 

package cn.lijunkui.task.jdk;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimerTask;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.lijunkui.task.own.SchedulerTask;

public class DemoTask extends TimerTask{
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Override
	public void run() {
		try {
			Thread.sleep(4*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		 log.info("DemoTask The time is now {}", dateFormat.format(new Date()));
	}

}
package cn.lijunkui.task.jdk;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;

public class TimerTest {
	
	private DemoTask demoTask;
	
	public TimerTest(DemoTask demoTask) {
		this.demoTask = demoTask;
	}
	public void run() throws ParseException {
		Timer timer = new Timer();
		long delay = 0;
		long intevalPeriod = 1 * 1000;
		//timer.scheduleAtFixedRate(demoTask, delay, intevalPeriod);//每秒执行一次
		//timer.scheduleAtFixedRate(demoTask, 1000, intevalPeriod);//延迟一秒后每秒执行一次
		String datetimeStr = "2018-10-16 15:00:00";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date firstTime = sdf.parse(datetimeStr);
		timer.schedule(demoTask, firstTime, intevalPeriod);//3点后开始执行 每秒执行一次
	}
}

 

package cn.lijunkui.task.jdk;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(value = 1)
public class DemoTaskRunner implements ApplicationRunner{

	@Override
	public void run(ApplicationArguments args) throws Exception {
		TimerTest test = new TimerTest(new DemoTask());
		test.run();
	}
}

schedule: 任务执行时间是2秒 设置的时间间隔是3秒 我们的任务是每3秒执行一次

schedule:  任务执行时间是4秒 设置的时间间隔是3秒 我们的任务是每4秒执行一次

 

 scheduleAtFixedRate:任务执行时间是2秒 设置的时间间隔是3秒 我们的任务是每3秒执行一次

 scheduleAtFixedRate:任务执行时间是4秒 设置的时间间隔是3秒 我们的任务是每4秒执行一次 

 

2.2  ScheduledExecutorService

Java SE5 java.util.concurrent里 ScheduledExecutorService 提供了新的任务调度的方式。他是采用线程池的方式来执行的,相对于 Timer 语法更为简单。  
 

package cn.lijunkui.task.jdk.scheduledExecutorService;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.lijunkui.task.own.SchedulerTask;

public class ScheduledExecutorTask implements Runnable{
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Override
	public void run() {
		try {
			Thread.sleep(4*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		 log.info("scheduledExecutorTask The time is now {}", dateFormat.format(new Date()));
	}
}
package cn.lijunkui.task.jdk.scheduledExecutorService;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorTest {
	private ScheduledExecutorTask task;
	public ScheduledExecutorTest(ScheduledExecutorTask task) {
		this.task = task;
	}
	public void run() {
		ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 
		
		 //当任务时间小于设置时间间隔则以设置的时间间隔为准
		//当任务执行时间大于设置的间隔时间时,真正间隔的时间由任务执行时间为准!
	   //service.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);//不延迟执行
	    //时间间隔是设置的间隔时间+执行任务的时间
	    //service.scheduleWithFixedDelay(task,0, 3, TimeUnit.SECONDS);//不延迟执行
		//只执行一次时间间隔是设置的间隔时间+执行任务的时间
	    service.schedule(task, 3, TimeUnit.SECONDS);
	}
}
package cn.lijunkui.task.jdk.timer;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import cn.lijunkui.task.jdk.scheduledExecutorService.ScheduledExecutorTask;
import cn.lijunkui.task.jdk.scheduledExecutorService.ScheduledExecutorTest;
@Component
@Order(value = 1)
public class DemoTaskRunner implements ApplicationRunner{

	@Override
	public void run(ApplicationArguments args) throws Exception {
		//TimerTest test = new TimerTest(new DemoTask());
		//test.run();
		ScheduledExecutorTest test = new ScheduledExecutorTest(new ScheduledExecutorTask());
		test.run();
	}
}

测试结果:

scheduleAtFixedRate: 任务执行时间是2秒 设置的时间间隔是3秒 我们的任务是每3秒执行一次

 

玩转springboot2.x之整合定时任务篇_第1张图片

scheduleAtFixedRate: 任务执行时间是4秒 设置的时间间隔是3秒 我们的任务是每4秒执行一次

scheduleWithFixedDelay : 任务执行时间是2秒 设置的时间间隔是3秒 我们的任务是每5秒执行一次

scheduleWithFixedDelay : 任务执行时间是4秒 设置的时间间隔是3秒 我们的任务是每7秒执行一次

schedule: 任务执行时间是2秒 设置的时间间隔是3秒 我们的任务是每5秒执行一次

schedule: 任务执行时间是4秒 设置的时间间隔是3秒 我们的任务是每7秒执行一次

通过上面测试scheduleAtFixedRate 和 scheduleWithFixedDelay  我们建议使用scheduleAtFixedRate 因为他的时间间隔更为合理。

3 springboot 集成 quartz

springboot 2.0 已经有了quartz 的start依赖,我们可以直接引入quartz 的start依赖 来使用quartz 了。

首先我们先引入quartz start依赖

		
		   org.springframework.boot
		   spring-boot-starter-quartz
		

定义quartz 的job

package cn.lijunkui.task.quartz.simple;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

import cn.lijunkui.task.own.SchedulerTask;
import cn.lijunkui.task.quartz.simple.service.OrderService;

public class SimpleJob  extends QuartzJobBean{
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Autowired
	private OrderService  orderService;//订单service
	private String serviceCode;//业务code
	

	public String getServiceCode() {
		return serviceCode;
	}
	public void setServiceCode(String serviceCode) {
		this.serviceCode = serviceCode;
	}

	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		
		System.out.println(serviceCode);
		 log.info("quartz simple The time is now {}", dateFormat.format(new Date()));
		orderService.delete();
	}

}

 创建quartz 的Config 同时定义 JobDetail 和 触发器 Trigger

package cn.lijunkui.task.quartz.simple;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SimpleJobConfig {
	@Bean
	public JobDetail simpleJobDetail() {
		
		return JobBuilder.newJob(SimpleJob.class).withIdentity("myJob").storeDurably()
				 	.usingJobData("serviceCode","delete overdue orders")
	                .build();
	}
	@Bean
	public Trigger simpleJobTrigger() {
		//定义每三秒执行一次
		SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever();
		//定义触发器
		return TriggerBuilder.newTrigger().forJob(simpleJobDetail()).withIdentity("myJobTrigger").withSchedule(simpleScheduleBuilder).build();
	}
}

定义注入的Job的Service 

package cn.lijunkui.task.quartz.simple.service;

import org.springframework.stereotype.Service;

@Service
public class OrderService {
	public void delete() {
		try {
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("delete data sucess....");
	}
}

测试日志:

orderService延时 2秒 任务是按照每3秒执行一次

 玩转springboot2.x之整合定时任务篇_第2张图片

orderService延时 6秒 任务是按照每3秒执行一次 

玩转springboot2.x之整合定时任务篇_第3张图片

 quartz 使用cron 表达式

cron 表达式操作方式和上面的基本一致 不过我们的job需要实现Job而不是使用继承的方式,我们这里定义2内容一致的job 具体代码如下:

package cn.lijunkui.task.quartz.cron;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import cn.lijunkui.task.own.SchedulerTask;
import cn.lijunkui.task.quartz.cron.service.LiveReminderService;

public class CronJob implements Job{
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Autowired
	private LiveReminderService  liveReminderService;//直播课提醒
	private String serviceCode;//业务code Live lesson reminder

	public String getServiceCode() {
		return serviceCode;
	}
	public void setServiceCode(String serviceCode) {
		this.serviceCode = serviceCode;
	}
    @Override  
    public void execute(JobExecutionContext context) throws JobExecutionException {
    	log.info("quartz cron The time is now {}", dateFormat.format(new Date()));
    	System.out.println("CronJob"+serviceCode);
    	liveReminderService.sendmessage();
    } 
}

 

package cn.lijunkui.task.quartz.cron;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;

import cn.lijunkui.task.quartz.cron.service.LiveReminderService;

public class CronJob2 implements Job{
	@Autowired
	private LiveReminderService  liveReminderService;//直播课提醒
	private String serviceCode;//业务code Live lesson reminder

	public String getServiceCode() {
		return serviceCode;
	}
	public void setServiceCode(String serviceCode) {
		this.serviceCode = serviceCode;
	}
    @Override  
    public void execute(JobExecutionContext context) throws JobExecutionException {
    	System.out.println("CronJob2"+serviceCode);
    	liveReminderService.sendmessage();
    } 
}

 定义cron 表达式 集成JobDetail 和 触发器 Trigger的manger类和上面定义的Config原理一样。

package cn.lijunkui.task.quartz.cron;

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.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

@Component
public class CronSchedulerJobManger {
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;
    
    public void scheduleJobs() throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        scheduleJob1(scheduler);
        //scheduleJob2(scheduler);   
    }  
    
    private void scheduleJob1(Scheduler scheduler) throws SchedulerException{
        JobDetail jobDetail = JobBuilder.newJob(CronJob.class) .withIdentity("job1", "group1")
        		.usingJobData("serviceCode","Live lesson reminder1").build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") .withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail,cronTrigger);   
    }  
      
    private void scheduleJob2(Scheduler scheduler) throws SchedulerException{
        JobDetail jobDetail = JobBuilder.newJob(CronJob2.class) .withIdentity("job2", "group2")
        		.usingJobData("serviceCode","Live lesson reminder2").build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group2") .withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail,cronTrigger);  
    } 
}

定义直播课提醒的service 

package cn.lijunkui.task.quartz.cron.service;

import org.springframework.stereotype.Service;

@Service
public class LiveReminderService {
	public void sendmessage() {
		try {
			Thread.sleep(10*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("xiaoming xiaoliu xiaoli has 3:00 Live broadcast lesson");
	}
}

 定义启动类 使项目一启动就执行 CronSchedulerJobManger 的定时任务。

package cn.lijunkui.task.quartz.cron;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class CronSchedulerRunner implements CommandLineRunner {
	@Autowired
	public CronSchedulerJobManger manger;
	@Override
	public void run(String... args) throws Exception {
		manger.scheduleJobs();
	}

}

测试结果:

任务执行时间4秒 定时任务设置时间间隔 5秒 实际执行效果是每5秒执行一次 

玩转springboot2.x之整合定时任务篇_第4张图片

任务执行时间10秒 定时任务设置时间间隔 5秒 实际执行效果是每5秒执行一次  

玩转springboot2.x之整合定时任务篇_第5张图片

demo工具和版本说明:

开发工具:Spring Tool Suite (STS)

jdk版本:1.8.0_144

springboot版本:2.0.5.RELEASE

 

查看源码 

你可能感兴趣的:(【SpringBoot】)