定时任务实现的几种方式
-
Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
-
ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
-
Spring Task:Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。
-
Quartz:这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。
二、SpringBoot中定时任务使用
1、引入依赖
只需要引入spring-boot-starter依赖就可以。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
2、 开启定时任务
在启动类上面加上@EnableScheduling注解即可开启定时任务。
@SpringBootApplication
@EnableScheduling
public class TaskApplication {
public static void main(String[] args) {
SpringApplication.run(TaskApplication.class);
}
}
3、创建定时任务类
创建一个定时任务类,在方法上加上@Scheduled注解,注解的参数可以配置时间。注意不要忘记加上@Component。
@Component
public class MyTask {
@Scheduled(fixedRate = 5000)
public void testTaskFirst() {
System.out.println("定时任务一:每五秒执行一次,当前时间:"+ LocalTime.now());
}
@Scheduled(cron = "0 28 03 ? * *")
public void testTaskSecond() {
System.out.println("定时任务二:指定每天3:26执行,当前时间:"+LocalTime.now());
}
}
测试结果:
三、@Scheduled注解参数说明
1、参数说明:
@Scheduled 参数可以接受两种定时的设置,一种是我们常用的cron="*/5 * * * * ?",一种是 fixedRate = 5000,两种都表示每隔五秒打印一下内容。
fixedRate 说明:
- @Scheduled(fixedRate = 5000) :上一次开始执行时间点之后5秒再执行。
- @Scheduled(fixedDelay = 5000) :上一次执行完毕时间点之后5秒再执行。
- @Scheduled(initialDelay=1000, fixedRate=5000) :第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次。
四springboot执行定时任务时阻塞
1.@Async //异步执行定时任务
@Component
@Async //异步执行定时任务
public class MyTask {
@Scheduled(fixedRate = 5000)
public void testTaskFirst() {
System.out.println("定时任务一:每五秒执行一次,当前时间:"+ LocalTime.now());
}
@Scheduled(cron = "0 28 03 ? * *")
public void testTaskSecond() {
System.out.println("定时任务二:指定每天3:26执行,当前时间:"+LocalTime.now());
}
}
2.在执行单个定时任务的时候也没有什么问题,但是如果同一时间段内执行多个定时任务,会造成线程阻塞,就是一定会等某一个定时任务执行完了之后才会执行下一个定时任务。
解决方案:
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
}
}
需要实现SchedulingConfigurer并重写setScheduler,将线程池的值设置的大一点,因为默认是单线程
五、Cron表达式与生成工具
Cron表达式生成工具地址:http://qqe2.com/cron