日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

SpringBoot源码分析之@Scheduled

發(fā)布時(shí)間:2023/11/27 生活经验 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot源码分析之@Scheduled 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Springboot寫上注解@Scheduled就可以實(shí)現(xiàn)定時(shí)任務(wù),

這里對(duì)其源碼做一點(diǎn)分析

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

配置文件100秒一次

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

?

重要的類ScheduledAnnotationBeanPostProcessor

@Nullableprivate 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?

找到自定義的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擁有execute()和submit()提交異步任務(wù)的基礎(chǔ)功能,ScheduledThreadPoolExecutor類實(shí)現(xiàn)了ScheduledExecutorService,該接口定義了ScheduledThreadPoolExecutor能夠延時(shí)執(zhí)行任務(wù)和周期執(zhí)行任務(wù)的功能。

ScheduledThreadPoolExecutor也兩個(gè)重要的內(nèi)部類:DelayedWorkQueueScheduledFutureTask??梢钥闯鯠elayedWorkQueue實(shí)現(xiàn)了BlockingQueue接口,也就是一個(gè)阻塞隊(duì)列,ScheduledFutureTask則是繼承了FutureTask類,也表示該類用于返回異步任務(wù)的結(jié)果。

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

到了schedule這里:

增加定時(shí)任務(wù)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

?

Spring如何添加鉤子函數(shù)

這里沒有注冊(cè)鉤子函數(shù)自然是null

進(jìn)Runtime.getRuntime().addShutdownHook(this.shutdownHook);

終于完了?

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

觸發(fā)定時(shí)

倒著看就知道怎么調(diào)用的,實(shí)際上是反射執(zhí)行上述方法的

invoke方法用來在運(yùn)行時(shí)動(dòng)態(tài)地調(diào)用某個(gè)實(shí)例的方法

這里實(shí)行了Runnable 接口:?

反射,線程,線程池 底層還是這些技術(shù)!需要好好研究這塊代碼,加深理解基本原理。

?

擴(kuò)展信息:SpringBoot中定時(shí)任務(wù)默認(rèn)是串行執(zhí)行 如何設(shè)置并行

SpringBoot 使用@Scheduled注解配置串行、并行定時(shí)任務(wù)

Spring Boot 中實(shí)現(xiàn)定時(shí)任務(wù)的兩種方式

總結(jié)

以上是生活随笔為你收集整理的SpringBoot源码分析之@Scheduled的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。