对于定时任务,在SpringBoot中只需要使用@Scheduled 这个注解就能够满足需求,它的出现也给我们带了很大的方便,我们只要加上该注解,并且根据需求设置好就可以使用定时任务了。
但是,我们需要注意的是,@Scheduled 并不一定会按时执行。
因为使用@Scheduled 的定时任务虽然是异步执行的,但是,不同的定时任务之间并不是并行的!!!!!!!!
在其中一个定时任务没有执行完之前,其他的定时任务即使是到了执行时间,也是不会执行的,它们会进行排队。
也就是如果你想你不同的定时任务互不影响,到时间就会执行,那么你最好将你的定时任务方法自己搞成异步方法,这样,定时任务其实就相当于调用了一个线程执行任务,一瞬间就结束了。比如使用:@Async
当然,也可以勉强将你的定时任务当做都会定时执行。但是,作为一个合格的程序员
那么,如何将@Scheduled实现的定时任务变成异步的呢?此时你需要对@Scheduled进行线程池配置。
package com.java.navtool.business.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.task.TaskExecutor;import org.springframework.scheduling.annotation.Async;import org.springframework.scheduling.annotation.EnableScheduling;import org.springframework.scheduling.annotation.SchedulingConfigurer;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import org.springframework.scheduling.config.ScheduledTaskRegistrar;import java.util.concurrent.Executor;import java.util.concurrent.Executors;import java.util.concurrent.ThreadPoolExecutor;/** * @author :mmzsblog.cn * @date :Created in 2021/7/27 17:46 * @description:spring-boot 多线程 @Scheduled注解 并发定时任务的解决方案 * @modified By: * @version: */@Configuration@EnableSchedulingpublic class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskExecutor()); } public static final String EXECUTOR_SERVICE = "scheduledExecutor"; @Bean(EXECUTOR_SERVICE) public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 设置核心线程数 executor.setCorePoolSize(Runtime.getRuntime().availableProcessors()); // 设置最大线程数 executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10); // 设置队列容量 executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10); // 设置线程活跃时间(秒) executor.setKeepAliveSeconds(10); // 设置默认线程名称 executor.setThreadNamePrefix("scheduled-"); // 设置拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown(true); return executor; }}附带介绍一下线程池的几个参数。需要彻底搞懂,不要死记硬背哦!
上个流程图,先试着自己看下能不能看懂:
