本文的核心内容:Spring Boot定时任务、Spring Boot定时任务线程池(多个任务同时执行)。
实现定时任务有很多方式,这里采用的是SpringTask的方式。
Spring Boot使用定时任务
1:Spring Boot项目启动类上加上 @EnableScheduling 注解
2:自定义Job @Scheduled(cron="") //定时触发事件
Schecduled注解的参数,诸如:
1.cron是设置定时执行的表达式,如 0 0/5 * * * ?每隔五分钟执行一次
2.zone表示执行时间的时区
3.fixedDelay 和fixedDelayString 表示一个固定延迟时间执行,上个任务完成后,延迟多长时间执行
4.fixedRate 和fixedRateString表示一个固定频率执行,上个任务开始后,多长时间后开始执行
5.initialDelay 和initialDelayString表示一个初始延迟时间,第一次被调用前延迟的时间
@Component
public class xxxJob{
@Scheduled(cron="")
public void xxxJob(){
//业务逻辑
}
}
其中Cron表达式可以设置任务执行的时间。具体如何书写不再详解,这不是这篇博客的主要内容。
到此,定时任务的简单使用就结束了。
SpringTask定时任务与多线程
下面介绍一些SpringTask定时任务的小知识。
1)假设你定义的任务1秒执行一次,然后让线程Sleep5秒,最后返回。观察打印的时间间隔
@Component
public class InitJob {
@Scheduled(cron = "")
public void initJob(){
if (true){
System.out.println(new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return;
}
}
}
这个例子想说明,如果你定时任务执行时间超过了定时任务时间间隔,任务下次开始时间会顺延到下个可以执行的时间间隔。
换句话说,如果你的定时任务间隔2秒,而任务执行了3秒,它会在第5秒,也就是第二个任务间隔后执行下一次的定时任务。
2)如果你定义两个Job,在每个Job中打印当前线程的名字,你会发现你所定义的多个任务是由同一个线程执行。
换句话说,许多任务由一个线程,串行执行的。
源码可以找到答案
从ScheduledAnnotationBeanPostProcessor类开始一路找下去。在ScheduledTaskRegistrar(定时任务注册类)中的ScheduleTasks中又这样一段判断:默认使用的是单线程池。
if (this.taskScheduler == null) {
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}
我们只需用调用这个方法显式的设置一个ScheduledExecutorService就可以达到并发的效果了。我们要做的是实现SchedulingConfigurer接口,重写configureTasks方法就OK了。
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executors;
/**
* 多线程执行定时任务
*/
@Configuration
//所有的定时任务都放在一个线程池中,定时任务启动时使用不同都线程。
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//设定一个长度5的定时任务线程池
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
}
}
这时,你在任务中打印当前线程名时,多个任务由多个线程同时执行。