SpringBoot配合线程池实现定时任务

本文介绍如何在SpringBoot项目中使用@EnableScheduling和@Scheduled注解实现定时任务,包括单线程执行、默认线程池多线程执行及自定义线程池执行定时任务的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值