一 定时任务
定时任务即系统在特定时间执行一段代码,它的场景应用非常广泛:
1.购买游戏的月卡会员后,系统每天给会员发放游戏资源。
2.管理系统定时生成报表。
3.定时清理系统垃圾
定时任务的实现主要有以下几种方式:
1.Java自带的java.util.Timer类,这个类允许调度一个java.util.TimerTask任务。使用这种方式可以让
程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
2.Quartz。这是一个功能比较强大的的调度器,可以让程序在指定时间执行,也可以按照某一个频度
执行,配置起来稍显复杂。
3.Spring3.0以后自带Spring Task,可以将它看成一个轻量级的Quartz,使用起来比 Quartz简单许
多,在课程中我们使用Spring Task实现定时任务
二 入门案例
2.1项目结构
2.2启动类开启定时任务
@SpringBootApplication
@EnableScheduling
public class Springbootdemo8Application {
public static void main(String[] args) {
SpringApplication.run(Springbootdemo8Application.class, args);
}
}
2.3任务案例
@Component
public class MyTask {
//定时任务方法,每秒执行一次
@Scheduled(cron = "* * * * * *")
public void task1(){
//显示当前是时间
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()));
}
}
三 Cron表达式
【1】Spring Task依靠Cron表达式配置定时规则。Cron表达式是一个字符串,分为6或7个域,每一个域代表一个含义,以空格隔开。有如下两种语法格式:
四 Cron实战案例
4.1案例
@Component
public class MyTask {
//定时任务方法,每秒执行一次
@Scheduled(cron = "* * * * * *")
public void task1(){
//显示当前是时间
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()));
}
@Scheduled(cron = "5,10,20,45 * * * * *")
public void task2(){
//显示当前是时间
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()));
}
@Scheduled(cron = "5-20 * * * * *")
public void task3(){
//显示当前是时间
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()));
}
@Scheduled(cron = "5/20 * * * * *")
public void task4(){
//显示当前是时间
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()));
}
}
五 Scheduled注解
@Scheduled写在方法上方,指定该方法定时执行。常用参数如下:
1.cron:cron表达式,定义方法执行的时间规则。
2.fixedDelay:任务立即执行,之后每隔多久执行一次,单位是毫秒,上一次任务结束后计算下次执行的时间。
3.fixedRate:任务立即执行,之后每隔多久执行一次,单位是毫秒,上一次任务开始后计算下次执行的时间。
4.initialDelay:项目启动后不马上执行定时器,根据initialDelay的值延时执行。
5.1案例
@Component
public class MyTask2 {
@Scheduled(fixedDelay = 5000)
public void task1() throws InterruptedException {
//显示当前是时间
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
Thread.sleep(1000);
System.out.println(sdf.format(new Date()));
}
}
六 多线程任务
【1】Spring Task定时器默认是单线程的,如果项目中使用多个定时器,
使用一个线程会造成效率低下。代码如下:
@Component
public class MyTask3 {
@Scheduled(cron = "* * * * * *")
public void task1() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+"线程执行任务1");
Thread.sleep(5000);
}
@Scheduled(cron = "* * * * * *")
public void task2() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+"线程执行任务2");
}
}
可见效率低下,任务1较浪费时间,会阻塞任务2的运行。此时我们可以给SpringTask配置线程池。
2】改进
配置多线程
@Component
public class SchedulingConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//创建线程池
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
}
}
多任务
@Component
public class MyTask3 {
@Scheduled(cron = "* * * * * *")
public void task1() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+"线程执行任务1");
Thread.sleep(5000);
}
@Scheduled(cron = "* * * * * *")
public void task2() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+"线程执行任务2");
}
}
任务1的阻塞并不会阻塞任务2的执行,这样效率就上来了