cron为cron表达式,用来表示该任务在日期时间维度执行频率,详细可参考cron表达式的文章
fixedRate:代表该任务的执行频率,单位毫秒,无论任务执行耗时多久,总是以该频率执行任务
fixedDelay:代表该任务的执行频率,单位毫秒,在上一次任务执行完后等待x毫秒后执行下次任务
前提:springboot通过scheduling实现的定时任务使用的线程有自己的线程池,默认大小为1,此时无法满足多个定时任务的情形,因此通常需要手动设置线程池的大小,以10为例。
有以下三种情形
1.使用fixedRate属性不加@Async注解、使用fixedRate属性加@Async注解
2.使用cron不加@Async注解、使用cron属性加@Async注解
3.使用fixedDelay不加@Async注解
@Component @EnableAsync @Slf4j public class ScheduledTasks { @Scheduled(fixedDelay = 3000) // @Scheduled(fixedRate = 3000) // @Scheduled(cron = "0/3 * * * * ?") // @Async(value = "myAsync") void contextLoads() throws InterruptedException { log.info("scheduled1 wait start"); Thread.sleep(4000); log.info("scheduled1 wait end"); log.info("scheduled task run.... " + Thread.currentThread().getName()); } // @Scheduled(cron = "0/3 * * * * ?") @Scheduled(fixedDelay = 3000) // @Scheduled(fixedRate = 3000) // @Async(value = "myAsync") void scheduled2() throws InterruptedException { log.info("scheduled2 wait start"); Thread.sleep(4000); log.info("scheduled2 wait end"); log.info("scheduled task2 run.... " + Thread.currentThread().getName()); } }
会实现无论任务执行耗时多久,下次任务始终会以规定的频率执行;
上述例子中若为fixedRate,则下次任务开始执行始终是在上次任务开始后的三秒;
若为cron,则下次任务开始执行始终为上次任务开始执行后的三秒,也就是上次任务开始时间为10:23:02,则下次任务开始时间为10:23:05,此种情况不受任务执行耗时影响。
此时若每次任务执行耗时比fixedRate的值小,则会在上次任务开始后的fixedRate毫秒后开始执行下次任务;
若每次执行任务耗时比fixedRate的值大,则会在上次任务执行后立刻执行下次任务,因为此时已经超过规定的执行频率的时间,因此需要立刻执行下次任务。
此时若每次任务执行耗时比cron表达式所表示的上次任务开始时间与下次任务开始时间的间隔小,则会以cron表达式表示的频率执行任务;
若每次任务执行耗时比cron表达式所表示的上次任务开始时间与下次任务开始时间的间隔大,则下次任务会在上次任务执行完成后再到达cron表达式所表示的任务开始执行的时刻开始执行任务,例如上述例子中上次任务开始时间为10:23:02,任务执行耗时4s,而以cron表达式表示的频率下次的执行时间为10:23:05,但是此时上次任务并没有执行完成,上次任务执行完成的时间为10:23:06,因此下次任务执行需要等到cron表达式表示的下一次任务执行的时刻也就是10:23:08.
使用fixedDelay属性时不能加@Async注解,否则会报错。
此时无论任务执行耗时是多少,下次任务开始执行的时间总是上次任务执行完成后的fixedDelay毫秒。
方式一:修改配置文件application.yml
spring.task.scheduling.pool.size = 10
方式二:配置类
@Configuration public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(Executors.newScheduledThreadPool(50)); } }
@Configuration public class ScheduleConfig { /** * 此处方法名为Bean的名字,方法名无需固定 * 因为是按TaskScheduler接口自动注入 */ @Bean public TaskScheduler taskScheduler(){ // Spring提供的定时任务线程池类 ThreadPoolTaskScheduler taskScheduler=new ThreadPoolTaskScheduler(); //设定最大可用的线程数目 taskScheduler.setPoolSize(10); return taskScheduler; } }
@Component public class AsyncScheduledTaskConfig { @Bean public Executor myAsync() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //最大线程数 executor.setMaxPoolSize(100); //核心线程数 executor.setCorePoolSize(10); //任务队列的大小 executor.setQueueCapacity(10); //线程前缀名 executor.setThreadNamePrefix("task-thread"); //线程存活时间 executor.setKeepAliveSeconds(30); /** * 拒绝处理策略 * CallerRunsPolicy():交由调用方线程运行,比如 main 线程。 * AbortPolicy():直接抛出异常。 * DiscardPolicy():直接丢弃。 * DiscardOldestPolicy():丢弃队列中最老的任务。 */ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); //线程初始化 executor.initialize(); return executor; } }
使用时只需在@Async注解中使用value属性指定线程线程池名称,也就是bean的名称,上述默认为方法名
Chile Address 版权所有
Powered by WordPress