博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot源码分析之@Scheduled
阅读量:1980 次
发布时间:2019-04-27

本文共 6047 字,大约阅读时间需要 20 分钟。

Springboot写上注解@Scheduled就可以实现定时任务,

这里对其源码做一点分析

@Servicepublic 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
beans = ((ListableBeanFactory) this.beanFactory).getBeansOfType(SchedulingConfigurer.class); List
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 

找到自定义的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

参考:

 

ScheduledThreadPoolExecutor继承了ThreadPoolExecutor,也就是说ScheduledThreadPoolExecutor拥有execute()和submit()提交异步任务的基础功能,ScheduledThreadPoolExecutor类实现了ScheduledExecutorService,该接口定义了ScheduledThreadPoolExecutor能够延时执行任务和周期执行任务的功能。

ScheduledThreadPoolExecutor也两个重要的内部类:DelayedWorkQueueScheduledFutureTask。可以看出DelayedWorkQueue实现了BlockingQueue接口,也就是一个阻塞队列,ScheduledFutureTask则是继承了FutureTask类,也表示该类用于返回异步任务的结果。

/**     * @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
(command, null, triggerTime(delay, unit))); delayedExecute(t); return t; }

到了schedule这里:

增加定时任务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 

 

跳出refresh

 

这里没有注册钩子函数自然是null

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

终于完了 

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

触发定时

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

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

这里实行了Runnable 接口: 

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

 

扩展信息:

转载地址:http://rlrpf.baihongyu.com/

你可能感兴趣的文章
tf dense layer两种创建方式的对比和numpy实现
查看>>
tf initializer
查看>>
tf 从RNN到BERT
查看>>
tf keras SimpleRNN源码解析
查看>>
tf keras Dense源码解析
查看>>
tf rnn输入输出的维度和权重的维度
查看>>
检验是否服从同一分布
查看>>
tf callbacks
查看>>
keras、tf、numpy实现logloss对比
查看>>
Ubuntu20.04安装微信
查看>>
Restful风格的使用
查看>>
Swagger基础入门整合SpringBoot
查看>>
MyBatisPlus简单入门(SpringBoot)
查看>>
攻防世界web进阶区NewsCenter详解
查看>>
攻防世界web进阶PHP2详解
查看>>
如何解决词达人问题(新)
查看>>
攻防世界web进阶区surpersqli详解
查看>>
攻防世界web进阶区easytornado详解
查看>>
攻防世界web进阶区web2详解
查看>>
xss-labs详解(上)1-10
查看>>