@Scheduled定时器逻辑分析

使用说明

  1. 定时器类型:
    1. triggerTask:触发task,继承实现Trigger#nextExecutionTime方法,设置任务触发逻辑
    2. cronTask:cron表达式的定时任务,@Scheduled(cron = "*/9 * * * * ?")
    3. fixedRateTask:固定频率执行的定时任务,@Scheduled(fixedRate = 2 * 1000),每隔2s执行一次
    4. fixedDelayTask:固定延迟的Task,@Scheduled(fixedDelay = 2 * 1000),任务完成后开始计时,2s后执行
  2. 自定义线程池:需要继承SchedulingConfigurer并实现configureTasks方法,为调度器设置线程池
     @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setTaskScheduler(new ThreadPoolTaskScheduler(....));
    }
    

代码分析

  • 主体是ScheduledAnnotationBeanPostProcessor,大概分为三步

    1. 构造processor:new SchedulingConfiguration
      • spring方法PostProcessorRegistrationDelegate#registerBeanPostProcessors实例化SchedulingConfiguration
      • SchedulingConfiguration中创建ScheduledAnnotationBeanPostProcessor
      • ScheduledAnnotationBeanPostProcessor构造方法中初始化ScheduledTaskRegistrar任务调度器
      • ScheduledTaskRegistrar中维护了各种任务的列表
        @Nullable
        private List<TriggerTask> triggerTasks;
        @Nullable
        private List<CronTask> cronTasks;
        @Nullable
        private List<IntervalTask> fixedRateTasks;
        @Nullable
        private List<IntervalTask> fixedDelayTasks;
        private final Map<Task, ScheduledTask> unresolvedTasks = new HashMap(16);
        private final Set<ScheduledTask> scheduledTasks = new LinkedHashSet(16);
        
    2. 扫描bean中的@Scheduled方法并保存:ScheduledAnnotationBeanPostProcessor#postProcessAfterInitialization
      • ScheduledAnnotationBeanPostProcessor继承DestructionAwareBeanPostProcessor, 实现了BeanPostProcessor#postProcessAfterInitialization后置处理器,处理@Scheduled的bean 1695279749692.png

      • 对于有@Scheduled的方法,进行ScheduledAnnotationBeanPostProcessor#processScheduled

        annotatedMethods.forEach((method, scheduledAnnotations) -> {
            scheduledAnnotations.forEach((scheduled) -> {
                this.processScheduled(scheduled, method, bean);
            });
        });
        
      • processScheduled中调用registrar调度器保存各类型任务

    3. 执行保存的定时任务:监听到ContextRefreshedEvent后,执行onApplicationEvent方法
      • ScheduledAnnotationBeanPostProcessor继承ApplicationListener,接收消息,执行ScheduledAnnotationBeanPostProcessor#onApplicationEvent方法
      • 方法中设置调度器的线程池TaskScheduler,后续执行调度器ScheduledTaskRegistrar#scheduleTasks方法,启动任务
  • 还有ThreadPoolTaskExecutor extends ExecutorConfigurationSupport

    初始化ThreadPoolTaskExecutor时实现继承方法ExecutorConfigurationSupport#afterPropertiesSet通过ThreadPoolTaskExecutor#initializeExcutor设置线程池excutor

使用总结

  • 所有定时任务放在一个线程池中,线程池线程数为1,任务串行,不同的任务会阻塞影响
  • 按照设定时间将任务放到延迟队列中
  • 对于时效性要求高的任务最好使用线程池自己控制