SpringBoot使用Scheduling實(shí)現(xiàn)定時任務(wù)的示例代碼
springboot實(shí)現(xiàn)定時任務(wù)
開啟springboot定時任務(wù)
- springboot實(shí)現(xiàn)定時任務(wù)很簡單,只需要在啟動類上加上
@EnableScheduling就可以
/**
* @author liouwb
*/
@SpringBootApplication
@EnableScheduling
public class SchedulerApplication{
public static void main(String[] args) {
SpringApplication.run(SchedulerApplication.class, args);
}
}- 編寫測試類
/**
* @author liouwb
*/
@Slf4j
@Component
public class TestJob {
/**
* 定時任務(wù)-串行
* 固定一秒執(zhí)行一次
*
* @author liouwb
*/
@Scheduled(cron = "0/1 * * * * ?")
public void testTask1() {
log.info("測試任務(wù)-1");
}
}- 執(zhí)行結(jié)果

- 下面測試,如果讓每次任務(wù)執(zhí)行5秒
/**
* 定時任務(wù)-串行
* 固定一秒執(zhí)行一次
*
* @author liouwb
*/
@Scheduled(cron = "0/1 * * * * ?")
public void testTask1() throws InterruptedException {
// 讓每次任務(wù)執(zhí)行5秒
Thread.sleep(5 * 1000);
log.info("測試任務(wù)-1");
}- 想要的結(jié)果是1一秒執(zhí)行一次
- 實(shí)際執(zhí)行結(jié)果,是6秒執(zhí)行一次,線程串行執(zhí)行
- 未達(dá)到想要的接口

原因分析:
@EnableScheduling注解默認(rèn)使用的是ThreadPoolTaskScheduler線程池,默認(rèn)線程數(shù)是1- 下面我們看下源碼
- 我們看先
@EnableScheduling注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}- 看下
SchedulingConfiguration類
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {
@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
return new ScheduledAnnotationBeanPostProcessor();
}
}- 看下
ScheduledAnnotationBeanPostProcessor類
public ScheduledAnnotationBeanPostProcessor() {
this.registrar = new ScheduledTaskRegistrar();
}- 看下
ScheduledTaskRegistrar類,這里使用的是TaskScheduler線程池 - 默認(rèn)的是
ThreadPoolTaskScheduler


配置線程池,讓定時任務(wù)指定并發(fā)執(zhí)行
- 配置線程池,實(shí)現(xiàn)
SchedulingConfigurer接口,實(shí)現(xiàn)configureTasks方法
/**
* 線程池配置
*
* @author liouwb
* @time 2023-07-27
*/
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskScheduler());
}
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
// 設(shè)置線程池數(shù)量
taskScheduler.setPoolSize(10);
// 設(shè)置線程池前綴
taskScheduler.setThreadNamePrefix("parallelScheduler-");
return taskScheduler;
}
}- 執(zhí)行結(jié)果

先要線程異步執(zhí)行
在啟動類上添加 @EnableAsync 注解
/**
* @author liouwb
*/
@SpringBootApplication
@EnableAsync
@EnableScheduling
public class SchedulerApplication{
public static void main(String[] args) {
SpringApplication.run(SchedulerApplication.class, args);
}
}- 再方法上添加
@Async注解便可以讓方法異步執(zhí)行
/**
* @author liouwb
*/
@Slf4j
@Component
public class TestJob {
/**
* 定時任務(wù)-串行
* 固定一秒執(zhí)行一次
*
* @author liouwb
*/
@Scheduled(cron = "0/1 * * * * ?")
public void testTask1() throws InterruptedException {
// 讓每次任務(wù)執(zhí)行5秒
Thread.sleep(5 * 1000);
log.info("測試任務(wù)-1");
}
@Async
@Scheduled(cron = "0/1 * * * * ?")
public void testTask2() {
log.info("測試任務(wù)-2");
}
}- 執(zhí)行結(jié)果,可以看到異步線程和并未用到設(shè)置的線程池

springboot異步線程池設(shè)置
springboot 異步線程池默認(rèn)使用的是 ThreadPoolTaskExecutor
ThreadPoolTaskExecutor 和 ThreadPoolTaskScheduler 都在 org.springframework.scheduling.concurrent 下

``
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {斷點(diǎn)可以看到默認(rèn)的異步線程池,前綴為 taskScheduler- ,默認(rèn)核心線程數(shù)為 10
默認(rèn)線程池名稱

- 下面我們自己配置異步線程池
/**
* 線程池配置
*
* @author liouwb
*/
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskScheduler());
}
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
// 設(shè)置線程池前綴
taskScheduler.setThreadNamePrefix("parallelScheduler-");
return taskScheduler;
}
/**
* 配置異步線程池
*
* @author liouwb
* @rutern org.springframework.core.task.TaskExecutor
*/
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 設(shè)置核心線程數(shù)
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
// 設(shè)置最大線程數(shù)
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10);
// 設(shè)置隊列容量
executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10);
// 設(shè)置線程活躍時間(秒)
executor.setKeepAliveSeconds(10);
// 設(shè)置默認(rèn)線程名稱
executor.setThreadNamePrefix("ansyScheduled-");
// 設(shè)置拒絕策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任務(wù)結(jié)束后再關(guān)閉線程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}- 執(zhí)行結(jié)果,可以看到配置的線程池都生效了

指定線程池執(zhí)行任務(wù)
- 可以設(shè)置多個線程池
/**
* 線程池配置
*
* @author liouwb
* @time 2023-07-27
*/
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskScheduler());
}
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
// 設(shè)置線程池前綴
taskScheduler.setThreadNamePrefix("parallelScheduler-");
return taskScheduler;
}
/**
* 配置異步線程池
*
* @author liouwb
* @rutern org.springframework.core.task.TaskExecutor
*/
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 設(shè)置核心線程數(shù)
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
// 設(shè)置最大線程數(shù)
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10);
// 設(shè)置隊列容量
executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10);
// 設(shè)置線程活躍時間(秒)
executor.setKeepAliveSeconds(10);
// 設(shè)置默認(rèn)線程名稱
executor.setThreadNamePrefix("ansyScheduled-");
// 設(shè)置拒絕策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任務(wù)結(jié)束后再關(guān)閉線程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
/**
* 配置異步線程池2
*
* @author liouwb
* @rutern org.springframework.core.task.TaskExecutor
*/
@Bean
public TaskExecutor taskExecutor2() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 設(shè)置核心線程數(shù)
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
// 設(shè)置最大線程數(shù)
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10);
// 設(shè)置隊列容量
executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10);
// 設(shè)置線程活躍時間(秒)
executor.setKeepAliveSeconds(10);
// 設(shè)置默認(rèn)線程名稱
executor.setThreadNamePrefix("異步線程池2-");
// 設(shè)置拒絕策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任務(wù)結(jié)束后再關(guān)閉線程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}- 在執(zhí)行的時候指定線程池的名稱
/**
* @author liouwb
*/
@Slf4j
@Component
public class TestJob {
/**
* 定時任務(wù)-串行
* 固定一秒執(zhí)行一次
*
* @author liouwb
*/
@Scheduled(cron = "0/1 * * * * ?")
public void testTask1() throws InterruptedException {
// 讓每次任務(wù)執(zhí)行5秒
Thread.sleep(5 * 1000);
log.info("測試任務(wù)-1");
}
/**
* 異步執(zhí)行
*
* @author liouwb
*/
@Async
@Scheduled(cron = "0/1 * * * * ?")
public void testTask2() {
log.info("測試任務(wù)-2");
}
/**
* 異步執(zhí)行
* 指定使用taskExecutor2線程池
*
* @author liouwb
*/
@Async(value = "taskExecutor2")
@Scheduled(cron = "0/1 * * * * ?")
public void testTask3() {
log.info("測試任務(wù)-指定線程池-3");
}
}- 執(zhí)行結(jié)果

以上就是SpringBoot使用Scheduling實(shí)現(xiàn)定時任務(wù)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Scheduling定時任務(wù)的資料請關(guān)注腳本之家其它相關(guān)文章!
- Spring中@EnableScheduling實(shí)現(xiàn)定時任務(wù)代碼實(shí)例
- Spring中的@EnableScheduling定時任務(wù)注解
- SpringBoot注解@EnableScheduling定時任務(wù)詳細(xì)解析
- springboot通過SchedulingConfigurer實(shí)現(xiàn)多定時任務(wù)注冊及動態(tài)修改執(zhí)行周期(示例詳解)
- Spring定時任務(wù)關(guān)于@EnableScheduling的用法解析
- springboot項目使用SchedulingConfigurer實(shí)現(xiàn)多個定時任務(wù)的案例代碼
- SpringBoot使用SchedulingConfigurer實(shí)現(xiàn)多個定時任務(wù)多機(jī)器部署問題(推薦)
- Spring Scheduling本地任務(wù)調(diào)度設(shè)計與實(shí)現(xiàn)方式
相關(guān)文章
基于mybatis中<include>標(biāo)簽的作用說明
這篇文章主要介紹了基于mybatis中<include>標(biāo)簽的作用說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02
Java web數(shù)據(jù)可視化實(shí)現(xiàn)原理解析
這篇文章主要介紹了Java web數(shù)據(jù)可視化實(shí)現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03
Springboot實(shí)現(xiàn)根據(jù)條件切換注入不同實(shí)現(xiàn)類的示例代碼
這篇文章主要介紹了Springboot實(shí)現(xiàn)根據(jù)條件切換注入不同實(shí)現(xiàn)類的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
SpringBoot2.0整合Shiro框架實(shí)現(xiàn)用戶權(quán)限管理的示例
這篇文章主要介紹了SpringBoot2.0整合Shiro框架實(shí)現(xiàn)用戶權(quán)限管理的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
如何對quartz定時任務(wù)設(shè)置結(jié)束時間
這篇文章主要介紹了如何對quartz定時任務(wù)設(shè)置結(jié)束時間問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12

