の@Scheduled SpringBootソースコード解析

定期的なタスクを達成することができ@Scheduled Springboot書き込みノート、

ここでは、そのソースコードの少し分析を行います

@Service
public class MyScheduled {

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

設定ファイル100秒

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

 

重要なクラスの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();
	}

豆 

MyScheduledカスタムを探します

最初のコードを見つけるために、ここで見リバースした後、さらに上の彼の割り当てられた場所を見つけるために

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));
				}

 


 

重要なクラスのScheduledThreadPoolExecutor

参考:https://www.jianshu.com/p/502f9952c09b

 

ScheduledThreadPoolExecutorの継承ThreadPoolExecutorのScheduledThreadPoolExecutorの実行()及び送信()非同期タスクの基本的な機能を提出していること、のScheduledThreadPoolExecutorクラス実装ScheduledExecutorServiceこのインタフェースはScheduledThreadPoolExecutorのタスクサイクルを実行するためのタスクおよび機能の実施を遅らせることができる規定します。

ScheduledThreadPoolExecutorのは、2つの重要な内部クラス:DelayedWorkQueueScheduledFutureTaskDelayedWorkQueueは、クラスは非同期タスクの結果を返すために使用された、ブロックキューであるインタフェースは、ScheduledFutureTaskはFutureTaskクラスを継承しているのBlockingQueueを達成見ることができます。

/**
     * @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;
    }

ここでのスケジュールを設定するには:

定期的なタスクを増やし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));
			}
		}
	}

トラバーサルのArrayList 

 

ジャンプリフレッシュ

 

フック関数の春を追加する方法

無登録フック関数は当然ヌルはありません

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

最後に完成 

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

触发定时

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

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

这里实行了Runnable 接口: 

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

 

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

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

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

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

おすすめ

転載: blog.csdn.net/21aspnet/article/details/104611794