纠纷奇闻社交美文家庭
投稿投诉
家庭城市
爱好生活
创业男女
能力餐饮
美文职业
心理周易
母婴奇趣
两性技能
社交传统
新闻范文
工作个人
思考社会
作文职场
家居中考
兴趣安全
解密魅力
奇闻笑话
写作笔记
阅读企业
饮食时事
纠纷案例
初中历史
说说童话
乐趣治疗

Spring定时任务玩出花

8月16日 温柔冢投稿
  1。项目概览
  我们首先来大概看下这个项目:
  这里和定时任务相关的配置主要在config包里边,其他的都是业务类代码,换句话说其他的都是常规的CURD,所以我这里主要和小伙伴们介绍config中的代码。2。整体思路
  我先来说说这个项目的整体思路,这样方便大家理解下面的内容。
  在这个项目中,每一个定时任务都由一个线程去处理,负责处理每一个定时任务的线程类是SchedulingRunnable,所有的线程都跑在一个线程池中,这个线程池是ThreadPoolTaskScheduler,这是一个专为定时任务设计的线程池(支持Cron表达式),它的底层其实就是大家所熟知的ScheduledThreadPoolExecutor。当有一个新的定时任务需要执行时,创建一个SchedulingRunnable线程,然后连同Cron表达式一起扔到ThreadPoolTaskScheduler池子里去执行就行了。3。配置分析
  几个配置类我们逐一来分析。3。1SpringContextUtils
  首先我们提供了一个SpringContextUtils工具类,这个工具类实现了ApplicationContextAware接口,通过这个工具类,我们可以从Spring容器中查询一个Bean或者判断Spring容器中是否存在某一个Bean,工具类的代码如下(我主要列出来了有哪些方法,具体实现大家可以参考:https:github。comlenvescheduling):ComponentpublicclassSpringContextUtilsimplementsApplicationContextAware{privatestaticApplicationContextapplicationCOverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{SpringContextUtils。applicationContextapplicationC}publicstaticObjectgetBean(Stringname){}publicstaticTTgetBean(ClassTrequiredType){}publicstaticTTgetBean(Stringname,ClassTrequiredType){}publicstaticbooleancontainsBean(Stringname){}publicstaticbooleanisSingleton(Stringname){}publicstaticC?extendsObjectgetType(Stringname){}}3。2SchedulingRunnable
  将来每一个定时任务执行的时候,我们都开启一个新的线程去执行这个定时任务,SchedulingRunnable就是关于这个线程的配置,我们来看下:publicclassSchedulingRunnableimplementsRunnable{privatestaticfinalLoggerloggerLoggerFactory。getLogger(SchedulingRunnable。class);privateStringbeanNprivateStringmethodNprivateSprivateObjecttargetBprivateMpublicSchedulingRunnable(StringbeanName,StringmethodName){this(beanName,methodName,null);}publicSchedulingRunnable(StringbeanName,StringmethodName,Stringparams){this。beanNamebeanNthis。methodNamemethodNthis。init();}privatevoidinit(){try{targetBeanSpringContextUtils。getBean(beanName);if(StringUtils。hasText(params)){methodtargetBean。getClass()。getDeclaredMethod(methodName,String。class);}else{methodtargetBean。getClass()。getDeclaredMethod(methodName);}ReflectionUtils。makeAccessible(method);}catch(NoSuchMethodExceptione){e。printStackTrace();}}Overridepublicvoidrun(){logger。info(定时任务开始执行bean:{},方法:{},参数:{},beanName,methodName,params);longstartTimeSystem。currentTimeMillis();try{if(StringUtils。hasText(params)){method。invoke(targetBean,params);}else{method。invoke(targetBean);}}catch(Exceptionex){logger。error(String。format(定时任务执行异常bean:s,方法:s,参数:s,beanName,methodName,params),ex);}longtimesSystem。currentTimeMillis()startTlogger。info(定时任务执行结束bean:{},方法:{},参数:{},耗时:{}毫秒,beanName,methodName,params,times);}Overridepublicbooleanequals(Objecto){if(thiso)if(onullgetClass()!o。getClass())SchedulingRunnablethat(SchedulingRunnable)o;if(paramsnull){returnbeanName。equals(that。beanName)methodName。equals(that。methodName)that。}returnbeanName。equals(that。beanName)methodName。equals(that。methodName)params。equals(that。params);}OverridepublicinthashCode(){if(paramsnull){returnObjects。hash(beanName,methodName);}returnObjects。hash(beanName,methodName,params);}}
  SchedulingRunnable实现了Runnable接口,这里的实现逻辑也比较简单,我们一起来看下:首先声明了beanName、methodName以及params分别作为定时任务执行的Bean的bean名称、方法名称以及方法参数。不知道小伙伴们是否记得我们上篇文章中介绍的该系统的用法,在添加一个定时任务时,我们需要传入相应的beanName、methodName以及params参数,传入后就来到这里了。另外还有targetBean和method分别表示beanName对应的对象以及methodName对应的对象,其中targetBean通过beanName从Spring容器中查找,method则通过methodName从targetBean中查找。在run方法中,通过反射去调用method方法,这也是定时任务执行时候的具体逻辑。另外,这里重写了equals和hashCode方法,这两个方法主要是比较了beanName、methodName以及params三个属性,换言之,如果这三个属性相同,则认为这是同一个对象(这三个属性相同表示这是同一个定时任务)。3。3SchedulingConfigConfigurationpublicclassSchedulingConfig{BeanpublicTaskSchedulertaskScheduler(){ThreadPoolTaskSchedulertaskSchedulernewThreadPoolTaskScheduler();taskScheduler。setPoolSize(4);taskScheduler。setRemoveOnCancelPolicy(true);taskScheduler。setThreadNamePrefix(TaskSchedulerThreadPool);returntaskS}}
  这里主要是配置一下ThreadPoolTaskScheduler,这个可以很方便的对重复执行的任务进行调度管理,相比于通过Java自带的周期性任务线程池ScheduleThreadPoolExecutor,ThreadPoolTaskScheduler对象支持根据Cron表达式创建周期性任务。
  既然是线程池,必然就有线程数量等问题,它的核心线程池大小就是我们配置的poolSize属性,最大线程池大小是Integer。MAXVALUE,keepAliveTime为0,这里用到的队列是DelayedWorkQueue,这个队列有一个属性privatefinalDelayQueuedqnewDelayQueue();对这个队列的操作实际是是对这个DelayQueue的操作,这个队列大小是Integer。MAXVALUE,所以线程数量肯定是够用了。
  其他配置就没啥好说的。3。4ScheduledTask
  ScheduledTask是ScheduledFuture的包装类,这个包装类中主要多了一个future属性,这个future属性表示TaskScheduler定时任务线程池的执行结果:publicfinalclassScheduledTask{volatileScheduledF?publicvoidcancel(){ScheduledF?futurethis。if(future!null){future。cancel(true);}}}3。5CronTaskRegistrar
  核心的方法都在这个里边。ComponentpublicclassCronTaskRegistrarimplementsDisposableBean{privatefinalMapRunnable,ScheduledTaskscheduledTasksnewConcurrentHashMap(16);AutowiredprivateTaskSchedulertaskSpublicTaskSchedulergetScheduler(){returnthis。taskS}publicvoidaddCronTask(Runnabletask,StringcronExpression){addCronTask(newCronTask(task,cronExpression));}publicvoidaddCronTask(CronTaskcronTask){if(cronTask!null){RunnabletaskcronTask。getRunnable();if(this。scheduledTasks。containsKey(task)){removeCronTask(task);}this。scheduledTasks。put(task,scheduleCronTask(cronTask));}}publicvoidremoveCronTask(Runnabletask){ScheduledTaskscheduledTaskthis。scheduledTasks。remove(task);if(scheduledTask!null)scheduledTask。cancel();}publicScheduledTaskscheduleCronTask(CronTaskcronTask){ScheduledTaskscheduledTasknewScheduledTask();scheduledTask。futurethis。taskScheduler。schedule(cronTask。getRunnable(),cronTask。getTrigger());returnscheduledT}Overridepublicvoiddestroy(){for(ScheduledTasktask:this。scheduledTasks。values()){task。cancel();}this。scheduledTasks。clear();}}
  稍微说下这个类:首先这个类实现了DisposableBean接口,实现这个接口就重写了destroy方法,以便在Bean销毁的时候,清除所有的定时任务。addCronTask(Runnable,String)方法用来添加一个定时任务,传两个参数,第一个是Runnable,也就是我们前面所说的定时任务,第二个则是一个Cron表达式。addCronTask(CronTask)方法也用来添加定时任务,添加之前先判断这个定时任务是否已经存在,如果已经存在,就先移除。然后将定时任务存入scheduledTasks中,存储的时候,key就是那个Runnable对象,value则是一个ScheduledTask对象。ScheduledTask对象从scheduleCronTask方法中获取,这也是整个系统最最核心的一段代码,调用taskScheduler对象把定时任务添加进去。removeCronTask方法用来移除一个定时任务,移除分为两部分:1。从scheduledTasks集合中找到定时任务并移除;2。取消定时任务的执行。最后的destroy方法就是一个常规方法,该移除移除,该清空清空。3。6InitTask
  这是一个处理数据库中已有定时任务的类。当系统启动时,首先从数据库中读取需要定时执行的任务,然后挨个加入定时任务执行器中:ComponentpublicclassInitTaskimplementsCommandLineRunner{AutowiredCronTaskRegistrarcronTaskRAutowiredSysJobServicesysJobSOverridepublicvoidrun(String。。。args)throwsException{ListSysJoblistsysJobService。getJobsByStatus(1);for(SysJobsysJob:list){cronTaskRegistrar。addCronTask(newSchedulingRunnable(sysJob。getBeanName(),sysJob。getMethodName(),sysJob。getMethodParams()),sysJob。getCronExpression());}}}查询所有状态为1的定时任务。遍历第一步查询出来的集合,添加定时任务。
  好啦,这就是整个项目最最核心的配置了,其他的代码都是一些业务层面的代码,乏善可陈,我就不啰嗦啦。4。定时任务怎么配
  有的小伙伴可能还不知道定时任务怎么配置,我这里稍微说两句。
  项目中提供了如下一个测试类:Component(schedulingTaskDemo)publicclassSchedulingTaskDemo{publicvoidtaskWithParams(Stringparams){System。out。println(执行有参示例任务:params);}publicvoidtaskNoParams(){System。out。println(执行无参示例任务);}}
  这是提前写好的,需要的时候我们配置的定时任务就是这里相关的参数,如下图:
  Bean名称、方法名称都和测试案例中的Bean一一对应。5。小结
  好啦,是不是很Easy?小伙伴们赶紧去尝试下吧!
  项目地址:GitHub:https:github。comlenveschedulingGitee:https:gitee。comlenvescheduling原文链接:https:mp。weixin。qq。comsskZ7uU7q1iH9QrV2EKiGOg
  原作者:江南一点雨
投诉 评论 转载

蒲英玮x雪铁龙凡尔赛C5X梭巡于时光与众生之中的法式先锋潮流视频加载中。。。当法系百年品牌邂逅留法艺术家,会激起怎样的火花?这样的梦幻联动就在现实上线了近日,东风雪铁龙领潮合伙人计划宣布扉艺所思FEELART合作艺术家蒲英玮……怎样煎鱼形美味鲜首先将鱼去鳞、去鳃,开肚去肠、洗净。然后用細盐,料酒腌一下,每500克鱼放盐5~10克,炒锅刷洗干净,放旺火上烧热,再用切开的生姜把鍋據一遍,然后在炒锅中放鱼的位置上淋一勺油,……为什么选择起亚K5凯酷?我们和95后车主聊了聊,原因竟然是这小张是个标准的95后打工人。自毕业那年,他就接过了父亲手里退役的德系老爷车。工作三年来,他不断经受各种来自这辆老车的精神和肉体双重折磨,譬如维修小毛病多,费油等等,由此产……Spring定时任务玩出花1。项目概览我们首先来大概看下这个项目:这里和定时任务相关的配置主要在config包里边,其他的都是业务类代码,换句话说其他的都是常规的CURD,所以我这里主要和小……小学体育单元教学中游戏的辅助作用论文游戏作为小学生十分热爱的娱乐方式,其具有形式多样、生动活泼、乐趣十足的特点。对小学生来说,游戏是最富有快乐和意义的活动,也是促进学习的有效方法。通过游戏教学,小学生容易受游戏情……资讯丨骁龙895将采用X2大核,安兔兔跑分有望上百万在前段时间,爆料人i冰宇宙曾表示,骁龙895将会由三星4nm工艺代工,而骁龙895则将会由台积电4nm工艺代工。大家都喜欢用骁龙895来称呼这颗代号为SM8450的新一代……会议通知2021年度实用眼科诊疗技术学习班即将启动加强眼科学术交流,共享国际学术成果。由中国非公立医疗机构协会眼科专业委员会联合爱尔眼科医院集团北京爱尔英智眼科医院共同举办的2021年度实用眼科诊疗技术学习班暨北京爱尔英……你相信毒辣车评被蔚来充值了吗?反正我不信?我觉得蔚来有没有充值不是最重要的,对于我们普通消费者来说最重要的是看他说的对不对,有没有污蔑!第一条:特斯拉是自动驾驶出事故最多的车型!这应该说的没错!tesladeat……2000元左右有哪些值得入手的手机?这几款就不错,颜值高配置1、红米K40红米K40使用高通骁龙870处理器,12GB内存,256GB存储空间,可以存储多达62000张照片或26000首歌曲,我们相信在性能方面它不会让人失望。在摄……苹果新品发布会召开,为何股价下跌,网络舆论不容乐观?今日凌晨,苹果秋季新品发布会如期召开,在本次发布会上,总共发布了五款新品,分别是iPhone13、iPhone13Pro、iPadmini6、iPad9和AppleWatch7……为什么大部分歌曲时长4分多5分多钟?因为当年一盘磁带正反两面刚好可以录60分钟的音乐,而唱片公司为歌手出一张专辑差不多要录1012首歌,所以每首歌大约就是45分钟长度,加起来一盘磁带刚好可以录下一个歌手的一张专辑……废品回收行业开启新时代,网友们纷纷表示这可能会改变人们的生活01hr斗转星移,日新月异。蒸汽时代早已过去,网络世界的无线电以光速传输着信息。互联网的出现,使着人们的生活发生了翻天覆地的变化,无论是衣食住行。随着社会不断……
任天堂Switch版饥荒已支持中文,并追加更新多种语言微软Xbox云游戏已支持Xbox平台,旧主机可玩次世代大作OPI与微软Xbox联名推出彩色指甲油,购买后可获得限定游戏EDG32GEN挺进决赛,与DK争夺英雄联盟S11总冠军英雄联盟首部动画剧集英雄联盟双城之战全球终极预告正式公布Theordinary第一次刷酸体验手术刀,梵高,喝咖啡,爬喜马拉雅山任正非到底在说什么?真要查偷税漏税,有几个公司是清白的?三星F52国行发布,定价1999元,对比K40,差距太明显浅谈如何提高高中语文的教学效率论文也谈小学科学教学思路论文荣耀30系列视觉盛宴?无辜大眼妆画法(无辜大眼妆的画法步骤)无公害丝瓜适合人群弃赛道,干地产?部分用户称iOS15。4太耗电!有机型续航降半,苹果称将进行揭开藏传佛教的色调之谜红与黄的神秘好意施惠意思表示的规定是什么?对孩子考试焦虑教师的辅导方法对孩子考试焦虑教师的辅导方法有哪《美丽有缘》女主角汤唯个性发型秀品味缕缕书香作文范文卫生间怎么布置比较合理卫生间布置有什么讲究小米air2pro怎么开启lhdclhdc在哪里设置下雨天心情的句子

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找美丽时装彩妆资讯历史明星乐活安卓数码常识驾车健康苹果问答网络发型电视车载室内电影游戏科学音乐整形