@Scheduled SpringBoot source code analysis of the

Springboot write notes @Scheduled regular tasks can be achieved,

Do a little analysis of its source code here

@Service
public class MyScheduled {

    @Scheduled(cron="${time.cron}")
    void paoapaoScheduled() {
        System.out.println("Execute at " + System.currentTimeMillis());
    }
}

Configuration file 100 seconds

time.cron=*/100 * * * * *

 

Important class ScheduledAnnotationBeanPostProcessor

@Nullable
	private BeanFactory beanFactory;
private void finishRegistration() {
		if (this.scheduler != null) {
			this.registrar.setScheduler(this.scheduler);
		}

		if (this.beanFactory instanceof ListableBeanFactory) {
			Map<String, SchedulingConfigurer> beans =
					((ListableBeanFactory) this.beanFactory).getBeansOfType(SchedulingConfigurer.class);
			List<SchedulingConfigurer> configurers = new ArrayList<>(beans.values());
			AnnotationAwareOrderComparator.sort(configurers);
			for (SchedulingConfigurer configurer : configurers) {
				configurer.configureTasks(this.registrar);
			}
		}

		if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) {
			Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type");
			try {
				// Search for TaskScheduler bean...
				this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, false));
			}
			catch (NoUniqueBeanDefinitionException ex) {
				logger.trace("Could not find unique TaskScheduler bean", ex);
				try {
					this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, true));
				}
				catch (NoSuchBeanDefinitionException ex2) {
					if (logger.isInfoEnabled()) {
						logger.info("More than one TaskScheduler bean exists within the context, and " +
								"none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +
								"(possibly as an alias); or implement the SchedulingConfigurer interface and call " +
								"ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +
								ex.getBeanNamesFound());
					}
				}
			}
			catch (NoSuchBeanDefinitionException ex) {
				logger.trace("Could not find default TaskScheduler bean", ex);
				// Search for ScheduledExecutorService bean next...
				try {
					this.registrar.setScheduler(resolveSchedulerBean(this.beanFactory, ScheduledExecutorService.class, false));
				}
				catch (NoUniqueBeanDefinitionException ex2) {
					logger.trace("Could not find unique ScheduledExecutorService bean", ex2);
					try {
						this.registrar.setScheduler(resolveSchedulerBean(this.beanFactory, ScheduledExecutorService.class, true));
					}
					catch (NoSuchBeanDefinitionException ex3) {
						if (logger.isInfoEnabled()) {
							logger.info("More than one ScheduledExecutorService bean exists within the context, and " +
									"none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +
									"(possibly as an alias); or implement the SchedulingConfigurer interface and call " +
									"ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +
									ex2.getBeanNamesFound());
						}
					}
				}
				catch (NoSuchBeanDefinitionException ex2) {
					logger.trace("Could not find default ScheduledExecutorService bean", ex2);
					// Giving up -> falling back to default scheduler within the registrar...
					logger.info("No TaskScheduler/ScheduledExecutorService bean found for scheduled processing");
				}
			}
		}

		this.registrar.afterPropertiesSet();
	}

bean 

Find MyScheduled custom

Reverse seen here first to find the code, and then further on to find his assigned place

if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) {
			Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type");
			try {
				// Search for TaskScheduler bean...
				this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, false));
			}
			catch (NoUniqueBeanDefinitionException ex) {
				logger.trace("Could not find unique TaskScheduler bean", ex);
				try {
					this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, true));
				}

 


 

Important class ScheduledThreadPoolExecutor

Reference: https://www.jianshu.com/p/502f9952c09b

 

ScheduledThreadPoolExecutor inherited ThreadPoolExecutor, that ScheduledThreadPoolExecutor have execute () and submit () submit basic functions of asynchronous tasks, ScheduledThreadPoolExecutor class implements ScheduledExecutorServicethis interface defines ScheduledThreadPoolExecutor can delay the implementation of tasks and functions to perform tasks cycle.

ScheduledThreadPoolExecutor also two important inner classes: DelayedWorkQueue and ScheduledFutureTask . It can be seen DelayedWorkQueue achieved BlockingQueue the interface, which is a blocking queue, ScheduledFutureTask is inherited FutureTask class, said class is used to return the results of asynchronous tasks.

/**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public ScheduledFuture<?> schedule(Runnable command,
                                       long delay,
                                       TimeUnit unit) {
        if (command == null || unit == null)
            throw new NullPointerException();
        RunnableScheduledFuture<?> t = decorateTask(command,
            new ScheduledFutureTask<Void>(command, null,
                                          triggerTime(delay, unit)));
        delayedExecute(t);
        return t;
    }

To schedule here:

Increase regular tasks ScheduledTaskRegistrar

protected void scheduleTasks() {
		if (this.taskScheduler == null) {
			this.localExecutor = Executors.newSingleThreadScheduledExecutor();
			this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
		}
		if (this.triggerTasks != null) {
			for (TriggerTask task : this.triggerTasks) {
				addScheduledTask(scheduleTriggerTask(task));
			}
		}
		if (this.cronTasks != null) {
			for (CronTask task : this.cronTasks) {
				addScheduledTask(scheduleCronTask(task));
			}
		}
		if (this.fixedRateTasks != null) {
			for (IntervalTask task : this.fixedRateTasks) {
				addScheduledTask(scheduleFixedRateTask(task));
			}
		}
		if (this.fixedDelayTasks != null) {
			for (IntervalTask task : this.fixedDelayTasks) {
				addScheduledTask(scheduleFixedDelayTask(task));
			}
		}
	}

Traversal arrayList 

 

Jump refresh

 

How to add a hook function Spring

There is no registered hook function naturally is null

进Runtime.getRuntime().addShutdownHook(this.shutdownHook);

Finally finished 

============================

触发定时

倒着看就知道怎么调用的,实际上是反射执行上述方法的

invoke方法用来在运行时动态地调用某个实例的方法

这里实行了Runnable 接口: 

反射,线程,线程池 底层还是这些技术!需要好好研究这块代码,加深理解基本原理。

 

扩展信息:SpringBoot中定时任务默认是串行执行 如何设置并行

SpringBoot 使用@Scheduled注解配置串行、并行定时任务

Spring Boot 中实现定时任务的两种方式

发布了1602 篇原创文章 · 获赞 1208 · 访问量 1238万+

Guess you like

Origin blog.csdn.net/21aspnet/article/details/104611794