问题描述
SpringBoot下使用定时任务,只需要加几个注释就可以了,详见:https://blog.terrynow.com/2021/07/10/java-spring-springboot-schedule-implement/
不过发现一个问题,就是定时任务比较多,且时间上有冲突的时候,在一个任务执行的时候,如果正好有另一个任务开始,另一个任务可能不会执行,因为SpringBoot默认的定时任务使用的是单列队的执行器(Executors.newSingleThreadScheduledExecutor() ),对同一个排程任务的执行总是同一个列队。如果任务的执行时间超过该任务的下一次执行时间,则会出现任务丢失,跳过该段时间的任务。
解决办法
让定时任务异步执行,给需要执行的Schedule方法加上@Async
@Component public class ScheduledTask { private static final Log log = LogFactory.getLog(ScheduledTask.class); //每30秒執行一次 @Async() @Scheduled(fixedRate = 1000 * 3) public void testSchedule0() { System.out.println("testSchedule0 called: " + Thread.currentThread().getName()); } /** * 测试8点21分执行,观察1分钟后和testSchedule2是否会同时执行 */ @Scheduled(cron = "0 21 8 ? * *") @Async public void testSchedule1() { for (int i = 0; i < 70; i++) { log.error("testSchedule1 called, " + Thread.currentThread().getName()); try { Thread.sleep(1000L); } catch (InterruptedException ignored) { } } } /** * 测试8点22分执行 */ @Scheduled(cron = "0 22 8 ? * *") @Async public void testSchedule2() { for (int i = 0; i < 70; i++) { log.warn("testSchedule2 called, " + Thread.currentThread().getName()); try { Thread.sleep(1000L); } catch (InterruptedException ignored) { } } } }
在SpringBoot主应用程序上要加上配置才能生效:@EnableAsync
@SpringBootApplication @EnableScheduling // 需要加@EnableAsync才能使用@Async @EnableAsync public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
办法2
配置SpringBoot让它启动另外的线程来执行定时任务(ThreadPoolTaskScheduler)
@Configuration @EnableAsync @EnableScheduling public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskScheduler()); } @Bean(name = "taskScheduler") public Executor taskScheduler() { ThreadPoolTaskScheduler scheduledExecutorService = new ThreadPoolTaskScheduler(); scheduledExecutorService.setPoolSize(10); scheduledExecutorService.setThreadNamePrefix("myTaskScheduler-"); scheduledExecutorService.setWaitForTasksToCompleteOnShutdown(false); return scheduledExecutorService; } }
文章评论