1.说明
项目中经常用到定时任务,SpringBoot已经提供了实现定时任务的注解 @EnableScheduling和@Scheduled,实现起来非常方便。定时任务的执行每次都会新开启一个线程,对系统资源有消耗, 可以通过线程池开启多线程调用定时任务
2.SpringBoot开启定时任务(单线程)
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
在主启动类添加注解@EnableScheduling
@SpringBootApplication
@EnableScheduling
public class SpringQuartzApplication{
public static void main(String[] args) {
SpringApplication.run(SpringQuartzApplication.class, args);
}
}
创建定时任务类,在执行定时任务的方法加上@Scheduled注解,这里有两个定时任务
@Configuration
public class StaticScheduleTask {
//定时任务1(2s执行一次)
@Scheduled(cron = "0/2 * * * * ? ")
public void scheDuleTask() {
System.out.println("test"+Thread.currentThread());
}
//定时任务2(5s执行一次)
@Scheduled(cron = "0/5 * * * * ? ")
public void scheDuleTask2() {
System.out.println("test2"+Thread.currentThread());
}
}
控制台输出结果,得出的结论是是单线程去执行多个定时任务
testThread[scheduling-1,5,main]
testThread[scheduling-1,5,main]
test2Thread[scheduling-1,5,main]
testThread[scheduling-1,5,main]
testThread[scheduling-1,5,main]
testThread[scheduling-1,5,main]
test2Thread[scheduling-1,5,main]
testThread[scheduling-1,5,main]
testThread[scheduling-1,5,main]
test2Thread[scheduling-1,5,main]
testThread[scheduling-1,5,main]
如果我设定一次任务为无限次数的for循环,那么有一个定时任务则永远无法执行,因为这是单线程。要解决这个问题要用的多线程去执行定时任务
3.默认线程池多线程执行定时任务
在主启动类通过@EnableAsync注解,允许开启异步线程
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class SpringQuartzApplication {
public static void main(String[] args) {
SpringApplication.run(SpringQuartzApplication.class, args);
}
}
在定时任务方法添加注解@Async注解开启异步线程执行
@Configuration
public class StaticScheduleTask {
@Async
@Scheduled(cron = "0/2 * * * * ? ")
public void scheDuleTask() {
System.out.println("test"+Thread.currentThread());
}
@Async
@Scheduled(cron = "0/5 * * * * ? ")
public void scheDuleTask2() {
System.out.println("test2"+Thread.currentThread());
}
}
控制台输出结果,SpringBoot采用默认线程池SimpleAsyncTaskExecutor来执行定时任务
testThread[SimpleAsyncTaskExecutor-1,5,main]
test2Thread[SimpleAsyncTaskExecutor-2,5,main]
testThread[SimpleAsyncTaskExecutor-3,5,main]
testThread[SimpleAsyncTaskExecutor-4,5,main]
testThread[SimpleAsyncTaskExecutor-5,5,main]
test2Thread[SimpleAsyncTaskExecutor-6,5,main]
testThread[SimpleAsyncTaskExecutor-7,5,main]
testThread[SimpleAsyncTaskExecutor-8,5,main]
test2Thread[SimpleAsyncTaskExecutor-9,5,main]
testThread[SimpleAsyncTaskExecutor-10,5,main]
testThread[SimpleAsyncTaskExecutor-11,5,main]
testThread[SimpleAsyncTaskExecutor-12,5,main]
test2Thread[SimpleAsyncTaskExecutor-13,5,main]
testThread[SimpleAsyncTaskExecutor-14,5,main]
testThread[SimpleAsyncTaskExecutor-15,5,main]
test2Thread[SimpleAsyncTaskExecutor-16,5,main]
testThread[SimpleAsyncTaskExecutor-17,5,main]
testThread[SimpleAsyncTaskExecutor-18,5,main]
4.自己设定线程池执行定时任务
线程池配置类,在配置类中添加上@EnableAsync注解
@Configuration
@EnableAsync
public class ExcutorConfig {
@Bean
public Executor excutor() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setThreadNamePrefix("thread-excutor");
taskScheduler.setPoolSize(10);
return taskScheduler;
}
@Bean
public Executor excutor1() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setThreadNamePrefix("thread-excutor1");
taskScheduler.setPoolSize(10);
return taskScheduler;
}
}
在定时任务中通过@Async注解指定线程池的名称,也就是我们创建的Bean对象的名称
@Configuration
public class StaticScheduleTask {
@Async("excutor") //excutor
@Scheduled(cron = "0/2 * * * * ? ")
public void scheDuleTask() {
System.out.println("test"+Thread.currentThread());
}
@Async("excutor1") //excutor1
@Scheduled(cron = "0/5 * * * * ? ")
public void scheDuleTask2() {
System.out.println("test2"+Thread.currentThread());
}
}
控制台输出结果,两个线程池异步执行定时任务,每个线程池的线程数量为10
test2Thread[thread-excutor11,5,main]
testThread[thread-excutor1,5,main]
testThread[thread-excutor1,5,main]
test2Thread[thread-excutor11,5,main]
testThread[thread-excutor1,5,main]
testThread[thread-excutor2,5,main]
testThread[thread-excutor1,5,main]
test2Thread[thread-excutor11,5,main]
testThread[thread-excutor3,5,main]
testThread[thread-excutor2,5,main]
testThread[thread-excutor4,5,main]
test2Thread[thread-excutor12,5,main]
testThread[thread-excutor1,5,main]
testThread[thread-excutor5,5,main]
test2Thread[thread-excutor11,5,main]
testThread[thread-excutor3,5,main]
testThread[thread-excutor6,5,main]
testThread[thread-excutor2,5,main]
test2Thread[thread-excutor13,5,main]
testThread[thread-excutor7,5,main]
testThread[thread-excutor4,5,main]
test2Thread[thread-excutor12,5,main]
testThread[thread-excutor8,5,main]
testThread[thread-excutor1,5,main]
testThread[thread-excutor9,5,main]
test2Thread[thread-excutor14,5,main]
testThread[thread-excutor5,5,main]
testThread[thread-excutor10,5,main]
test2Thread[thread-excutor11,5,main]
testThread[thread-excutor3,5,main]