安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

Quartz的执行流程分析

5月17日 颜如初投稿
  一、QuartzSchedulerThread的run方法大致阐述
  先说一下run方法的执行时机:
  当Quartzscheduler执行start方法时,方法体中有一句
  schedThread。togglePause(false);,接着就会调用QuartzSchedulerThread下的togglePause方法,将paused置为false,在此之后,QuartzSchedulerThread下的run方法开始真正运行通知主处理循环在下一个可能的点暂停voidtogglePause(booleanpause){synchronized(sigLock){if(paused){signalSchedulingChange(0);}else{sigLock。notifyAll();}}}复制代码publicvoidrun(){intacquiresFailed0;这里就是判断调度器是否该停止,如果没有收到信号的话,这个调度器是一直处于循环之中的while(!halted。get()){try{这里是检查我们是否应该暂停synchronized(sigLock){我们在初始化的时候,paused是置为true的,因此在上文中,我们才说当Quartzscheduler执行start方法时调用togglePause,将paused置为false,run方法才开始运行也是因为此处的判断while(paused!halted。get()){try{sigLock。wait(1000L);}catch(InterruptedExceptionignore){}acquiresFailed0;}if(halted。get()){}}如果从作业存储中读取一直失败(例如数据库关闭或重新启动)就会等待一段时间if(acquiresFailed1){try{这里就是计算延迟时间longdelaycomputeDelayForRepeatedErrors(qsRsrcs。getJobStore(),acquiresFailed);Thread。sleep(delay);}catch(Exceptionignore){}}从线程池拿出空闲可利用的线程数量这里多谈一嘴blockForAvailableThreads()方法它是一个阻塞式方法,直到至少有一个可用线程。intavailThreadCountqsRsrcs。getThreadPool()。blockForAvailableThreads();if(availThreadCount0){ListOperableTlongnowSystem。currentTimeMillis();清除信号调度变更clearSignaledSchedulingChange();try{如果可用线程数量足够那么就是30后再次扫描,acquireNextTriggers方法的三个参数的意思分别是:idleWaitTime:为如果没有的再次扫描的时间,默认是privatestaticlongDEFAULTIDLEWAITTIME30L1000L;30秒Math。min(availThreadCount,qsRsrcs。getMaxBatchSize()):这里的意思就是一次最多能取几个出来batchTimeWindow:默认是0,同样是一个时间范围,如果有两个任务只差一两秒,而执行线程数量满足及batchTimeWindow时间也满足的情况下就会两个都取出来具体的方法的执行,后文再看triggersqsRsrcs。getJobStore()。acquireNextTriggers(nowidleWaitTime,Math。min(availThreadCount,qsRsrcs。getMaxBatchSize()),qsRsrcs。getBatchTimeWindow());acquiresFailed0;if(log。isDebugEnabled()){。。。}在获取到triggers触发器不为空后,trigger列表是以下次执行时间排序查出来的if(triggers!null!triggers。isEmpty()){nowSystem。currentTimeMillis();取出集合中最早执行的触发器获取它的下一个触发时间longtriggerTimetriggers。get(0)。getNextFireTime()。getTime();longtimeUntilTriggertriggerT判断距离执行时间是否大于2毫秒while(timeUntilTrigger2){synchronized(sigLock){if(halted。get()){}判断是不是距离触发事件最近的,if(!isCandidateNewTimeEarlierWithinReason(triggerTime,false)){try{没有的话,就进行阻塞,稍后进行执行nowSystem。currentTimeMillis();timeUntilTriggertriggerTif(timeUntilTrigger1)sigLock。wait(timeUntilTrigger);}catch(InterruptedExceptionignore){}}}if(releaseIfScheduleChangedSignificantly(triggers,triggerTime)){}nowSystem。currentTimeMillis();timeUntilTriggertriggerT}thishappensifreleaseIfScheduleChangedSignificantlydecidedtoreleasetriggersif(triggers。isEmpty())settriggerstoexecutingListTriggerFiredResultbndlesnewArrayListTriggerFiredResult();booleangoAsynchronized(sigLock){goAhead!halted。get();}if(goAhead){try{开始根据需要执行的trigger从数据库中获取相应的JobDetail同时这一步也更新了triggers的状态,稍后会讲到ListTriggerFiredResultresqsRsrcs。getJobStore()。triggersFired(triggers);if(res!null)}catch(SchedulerExceptionse){qs。notifySchedulerListenersError(Anerroroccurredwhilefiringtriggerstriggers,se);for(inti0;itriggers。size();i){qsRsrcs。getJobStore()。releaseAcquiredTrigger(triggers。get(i));}}}将查询到的结果封装成为TriggerFiredResultfor(inti0;ibndles。size();i){TriggerFiredResultresultbndles。get(i);TriggerFiredBundle用于将执行时数据从JobStore返回到QuartzSchedulerThread。TriggerFiredBundlebndleresult。getTriggerFiredBundle();Exceptionexceptionresult。getException();if(exceptioninstanceofRuntimeException){getLog()。error(RuntimeExceptionwhilefiringtriggertriggers。get(i),exception);qsRsrcs。getJobStore()。releaseAcquiredTrigger(triggers。get(i));}if(bndlenull){qsRsrcs。getJobStore()。releaseAcquiredTrigger(triggers。get(i));}JobRunStry{把任务封装成JobRunShell线程任务,JobRunShellextendsSchedulerListenerSupportimplementsRunnable是实现了Runnable接口的然后放到线程池中跑动。shellqsRsrcs。getJobRunShellFactory()。createJobRunShell(bndle);shell。initialize(qs);}catch(SchedulerExceptionse){qsRsrcs。getJobStore()。triggeredJobComplete(triggers。get(i),bndle。getJobDetail(),CompletedExecutionInstruction。SETALLJOBTRIGGERSERROR);}别看这里是个if判断但是这里就是将obshell放进线程池执行的地方利用的就是booleanrunInThread(Runnablerunnable);方法这个方法的作用就是在下一个可用的Thread中执行给定Runnableif(qsRsrcs。getThreadPool()。runInThread(shell)false){getLog()。error(ThreadPool。runInThread()returnfalse!);qsRsrcs。getJobStore()。triggeredJobComplete(triggers。get(i),bndle。getJobDetail(),CompletedExecutionInstruction。SETALLJOBTRIGGERSERROR);}}while(!halted)}}else{if(availThreadCount0)shouldneverhappen,ifthreadPool。blockForAvailableThreads()while(!halted)}longnowSystem。currentTimeMillis();longwaitTimenowgetRandomizedIdleWaitTime();longtimeUntilContinuewaitTsynchronized(sigLock){。。。。}}。。。。}while(!halted)。。。。}复制代码二、一些细节2。1、先获取线程池中的可用线程数量
  (若没有可用的会阻塞,直到有可用的);intavailThreadCountqsRsrcs。getThreadPool()。blockForAvailableThreads();复制代码2。2、获取30m内要执行的trigger
  (即acquireNextTriggers)
  我们来看一看acquireNextTriggers方法
  首先说acquireNextTriggers具体实现是在JobStoreSupport中,同时quartz与数据库关联的实现大都在JobStoreSupport中,当然更具体的SQL执行还是在DriverDelegate接口下的。
  acquireNextTriggers做了哪些事情呢?
  我们看看这两个方法:
  首先看第一个acquireNextTrigger(conn,noLaterThan,maxCount,timeWindow);
  主要就是获取下一个30m内可执行的triggers的触发器,在里面JobStoreSupport从数据库取出triggers时是按照nextFireTime排序的
  更具体的就需要大家点进方法去看啦另外里面还包含triggers状态的变更,属于是更加细节化的东西。
  第二个就是获取到触发的触发记录
  然后在执行executeInNonManagedTXLock时,是需要先获得锁,之后再在提交时释放锁的。
  待直到获取的trigger中最先执行的trigger在2ms内;if(triggers!null!triggers。isEmpty()){nowSystem。currentTimeMillis();longtriggerTimetriggers。get(0)。getNextFireTime()。getTime();longtimeUntilTriggertriggerTwhile(timeUntilTrigger2){。。。}}复制代码2。3、triggersFired(triggers)
  ListresqsRsrcs。getJobStore()。triggersFired(triggers);
  这一步看着只是获取了List对象,实际上在triggersFired(triggers)方法中隐藏了很多东西
  首先查询,确保触发器没有被删除、暂停或完成。。。,就更新firedTrigger的statusSTATEEXECUTING;代码的注释上还说,如果没有这些就会将状态该为deleted
  另外就是更新触发触发器:更新trigger下一次触发的时间;更新trigger的状态:
  如果下一次的执行时间为空,状态则改为STATECOMPLETE
  在执行executeInNonManagedTXLock方法时,提交前先获得锁,transOwnergetLockHandler()。obtainLock(conn,lockName);
  最后是释放锁:commitConnection(conn);2。4、创建JobRunShell,放进线程池执行
  针对每个要执行的trigger,创建JobRunShell,并放入线程池执行:
  然后由execute:执行job
  更详细的看不下去啦
  来源:https:juejin。cnpost7131671438901116935
投诉 评论 转载

Quartz的执行流程分析一、QuartzSchedulerThread的run方法大致阐述先说一下run方法的执行时机:当Quartzscheduler执行start方法时,方法体中有一句……各位阴谋论爱好者,请放过林生斌吧林生斌再度登上热搜榜,这次是因为有人查到,他持股的服装公司状态从存续变更为注销。也就是说,他的公司已解散。先丧妻丧子,又遭铺天网暴,现在事业尽毁,林生斌可谓是惨上加惨。……双眼皮形态不对称,有时候微调就能达到理想效果汤女士的初眼形态其实还不错,除了双眼皮形态不规整,其他并没有什么大问题。像我经常说的上睑下垂,肿眼泡,脂肪堆积,皮肤松弛等,均没有在她身上体现。所以这次面诊时间没有很长,……京媒给国足点赞!李霄鹏这么决绝,让教练组上,拼劲都不会差北京时间3月24日23:00,世预赛亚洲区12强赛B组第9轮,中国男足将对阵沙特阿拉伯男足,赛前国足主帅李霄鹏发话:虽然失去了进军世界杯的机会,但要为中国足球的脸面而战!此番言……春季风邪易侵体,这些身体部位最易受伤据保健时报消息本报记者燕声春季小心风邪伤身春季晨曦初露,万物复苏,一派大好春光。但春季风邪较盛,《黄帝内经》中说:风者百病之长也。春季多风善行数变,从口鼻长驱……苹果再次砍单,iPhoneSE削减订单苹果上月推出iPhoneSE3,原本预期将承担推动老用户换新,以及吸引安卓用户跳槽的重任,实际表现却差强人意。市场不断下调新机出货量预期,最新一份预测报告显示大幅砍单23,苹果……自取其辱!C罗自荐遭拒,拜仁高层嘲讽,2900万年薪你不配上最近一段时间,关于C罗想要离开曼联的风闻不绝于耳。近日,《阿斯报》表示,C罗想要加盟的球队是拜仁。德国媒体Sport1报道,C罗的确经过门德斯向拜仁自荐,但被拒之门外。……天柱山三祖寺三祖寺,位于潜山城西北9公里天柱山谷口的凤形山。此地群山环抱,溪谷幽深,山谷中突兀一峰,宛如一只蹁跹的彩凤,故名凤形山。这里是一个天然谷口,清澈的山谷流泉,从凤形山西侧流出,经……2022年Q1全球智能手机出货量排名市场调研机构(Canalys)近日公布了2022年第一季度全球智能手机出货量情况:由于疫情及战争等多重原因,导致全球的经济状况都欠佳,智能手机的出货量接连下降,而这个季度下降了……奔跑吧雨天路透人员变化大,白鹿杨颖古装比美区别明显最近《奔跑吧》也开始了录制,跑男真的是小编见过坚持最久的综艺了。人走了一波又一波,可是综艺依旧照常录制,我们来看看这次的人员都有谁吧!周深小编真的太喜欢周深了……夏季体内湿气重,6味中药泡水喝,健脾又除湿进入夏季,由于天气比较炎热,又很容易下雨,就会导致空气中弥漫很多的湿气,再加上夏季人们比较喜欢吃凉的食物,会导致出的汗骤然停止,会导致水湿之气停在体内的肌肉、筋脉、筋骨等部位,……鹿晗与43岁邓超同框生图曝光鹿晗是一位特别有责任感的北京男孩,在与关晓彤谈恋爱后,他为了给女友安全感,不惜在事业最顶峰的时候官宣了恋情,一夜之间掉粉无数,事业也差点被毁掉了。好在这段恋情没有让鹿晗赌……
DNF8。25蝴蝶套新时装!枪手至尊天空出现,外观比机甲神器蛋白质摄入越多越好?高蛋白饮食导致的这些疾病你一定要知道关节运动指令(MoveJ)绿洲启元新玩法,带上你的队友开启全新夺笋之旅吧阿娇的穿搭有了肉眼可见的进步,白衬衫配长筒靴,又美又飒价值高达2000万美元的Yeezys阿迪达斯和耐克运动鞋将被有一种帅叫男明星穿白衬衫,儒雅又绅士,哪一位穿出来的果更好?6张新面孔进入前10,城商行迎来大变局保罗布克非真正核心?养着内线猛兽却不用,太阳又被逼到悬崖边iQOO10Pro对比小米12SPro你怎么选雪上加霜!曝中超球队没钱比赛欲向足协借钱,光路费就要几百万田径天才横空出世!百米9秒98200米破20秒跳远超8米,史夏天应多吃绿豆芽,生豆芽又出新方法,三天生出白白胖胖的绿豆芽假释考验期满后犯新罪撤销假释吗?能吓跑便秘的食物!帮助你最快最有效地排便天语t780刷机教程详解图解3款历史名酒,有老字号也有国家地理标志产品,如今没落圣罗兰粉底液怎么样圣罗兰粉底液多少钱一瓶脑供血不足会发生很多问题,这几个表现要注意,来预防脑供血不足多高的稳定年收入可以吸引你辞职去创业?口腔溃疡是什么为什么会得口腔溃疡怎么判断虎皮鹦鹉是不是生病了做期货交易7年,亏损420万元,把所有的技术都学会了为什么还家乡的凉皮

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利