- 921. Minimum Add to Make Parentheses Valid 使括号有效的最少添加
- 915. Partition Array into Disjoint Intervals 分割数组
- 932. Beautiful Array 漂亮数组
- 940. Distinct Subsequences II 不同的子序列 II
Quartz框架在执行任务中可能会由于停电,宕机等原因,有一段没有去调度任务,但是有些任务可能刚好应该在这个时间内执行,此时就会出现在本该执行的时间没有执行的情况。这种情况就叫做misfire了。
为了解决这个问题,Quartz框架也是做出了应对,它提供了多种可选的misfire处理策略,在添加任务时就可以配置,之后在任务misfire时就会根据配置的策略去处理。
Quartz在JobStoreSupport类中声明了一个MisFireHandler线程,用于去扫描QRTZ_TRIGGERS表,检查有没有trigger misfire了。这个线程会在Scheduler start的时候初始化,之后就会一直工作。Run方法中的逻辑如下:
public void run() {
while (!shutdown) {
long sTime = System.currentTimeMillis();
RecoverMisfiredJobsResult recoverMisfiredJobsResult = manage();
if (recoverMisfiredJobsResult.getProcessedMisfiredTriggerCount() > 0) {
signalSchedulingChangeImmediately(recoverMisfiredJobsResult.getEarliestNewTime());
}
if (!shutdown) {
long timeToSleep = 50l; // At least a short pause to help balance threads
if (!recoverMisfiredJobsResult.hasMoreMisfiredTriggers()) {
timeToSleep = getMisfireThreshold() - (System.currentTimeMillis() - sTime);
if (timeToSleep <= 0) {
timeToSleep = 50l;
}
if(numFails > 0) {
timeToSleep = Math.max(getDbRetryInterval(), timeToSleep);
}
}
try {
Thread.sleep(timeToSleep);
} catch (Exception ignore) {
}
}//while !shutdown
}
}
从代码可以看到,首先调用了manage方法,去执行了一次misfire的处理操作,拿到了一个RecoverMisfiredJobsResult的实例,如果有misfire的trigger被处理了,则要立即更新一次调度信号,之后线程至少会sleep50ms,以平衡线程的执行。所以主要需要看一下manage方法。其中调用了doRecoverMisfires,该方法中又调用了RecoverMisfireJobs方法。该方法实现了主要的业务逻辑,第一步:
// If recovering, we want to handle all of the misfired
// triggers right away.
int maxMisfiresToHandleAtATime =
(recovering) ? -1 : getMaxMisfiresToHandleAtATime();
List<TriggerKey> misfiredTriggers = new LinkedList<TriggerKey>();
long earliestNewTime = Long.MAX_VALUE;
// We must still look for the MISFIRED state in case triggers were left
// in this state when upgrading to this version that does not support it.
boolean hasMoreMisfiredTriggers =
getDelegate().hasMisfiredTriggersInState(
conn, STATE_WAITING, getMisfireTime(),
maxMisfiresToHandleAtATime, misfiredTriggers);
去QRTZ_TRIGGERS表查最大maxMisfiresToHandleAtTime个misfire的triggers,执行的sql语句如下:
String SELECT_HAS_MISFIRED_TRIGGERS_IN_STATE = "SELECT "
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + " FROM "
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE "
+ COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST + " AND NOT ("
+ COL_MISFIRE_INSTRUCTION + " = " + Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY + ") AND "
+ COL_NEXT_FIRE_TIME + " < ? "
+ "AND " + COL_TRIGGER_STATE + " = ? "
+ "ORDER BY " + COL_NEXT_FIRE_TIME + " ASC, " + COL_PRIORITY + " DESC";
如果有misfire的triggers,则向下进行第二步,处理misfire:
for (TriggerKey triggerKey: misfiredTriggers) {
OperableTrigger trig =
retrieveTrigger(conn, triggerKey);
if (trig == null) {
continue;
}
doUpdateOfMisfiredTrigger(conn, trig, false, STATE_WAITING, recovering);
if(trig.getNextFireTime() != null && trig.getNextFireTime().getTime() < earliestNewTime)
earliestNewTime = trig.getNextFireTime().getTime();
}
return new RecoverMisfiredJobsResult(
hasMoreMisfiredTriggers, misfiredTriggers.size(), earliestNewTime);
retrieveTrigger方法是从QRTZ_TRIGGERS表中查询出trigger的数据,doUpdateOfMisfiredTrigger方法中调用了
trig.updateAfterMisfire(cal);
该方法的逻辑就是根据misfire的策略去更新nextFireTime,然后会调用storeTrigger方法去更新QRTZ_TRIGGERS表中该trigger的数据。那Quartz好像到目前为止还是没有执行任务啊,misfire还是没有处理啊。别急,看一下updateAfterMisfire方法,以cron类型的trigger中的该方法为例:
int instr = getMisfireInstruction();
if(instr == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY)
return;
if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) {
instr = MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;
}
if (instr == MISFIRE_INSTRUCTION_DO_NOTHING) {
Date newFireTime = getFireTimeAfter(new Date());
while (newFireTime != null && cal != null
&& !cal.isTimeIncluded(newFireTime.getTime())) {
newFireTime = getFireTimeAfter(newFireTime);
}
setNextFireTime(newFireTime);
} else if (instr == MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) {
setNextFireTime(new Date());
}
可以看到,如果instr是立即触发一次,那么nextFireTime就会被设置成当前时间,接下来又调用了storeTrigger方法去把trigger的状态置为了WAITING。所以就会被QuartzShcedulerThread线程扫描到,立即执行一次。就实现了misfire的处理,其他的misfire的策略处理方式类似,都是通过更改下一次触发时间决定的。SimpleTriggerImpl中的updateAfterMisfire方法实现有所不同,出去更改nextFireTime还涉及到了次数的处理,有需要的可以自己看下。
有关QuartzSchedulerThread的执行逻辑的可以看链接:Quartz执行逻辑(一)QuartzSchedulerThread介绍.
版权声明:「DDKK.COM 弟弟快看,程序员编程资料站」本站文章,版权归原作者所有
刚接触 Quartz,我对简单形状、渐变和阴影的绘制速度感到好奇;特别将 Quartz 绘图功能与 iPhone 上的 Quartz 图像绘制进行比较。 假设我需要绘制一个填充、描边和阴影的矩形。我假
我遇到了一个问题,即在包含要运行的类文件的应用程序之前部署 quartz-service.xml(使用 quartz 1.8.6 和 JBOSS 5.1.x)。有没有办法延迟 quartz 的启动?
我正在研究使用Quartz Scheduler,并且想知道是否可以按时间而不是按时间调度作业,而可以在另一个作业完成时进行调度。因此,当作业A完成时,它将启 Action 业B。完成后,它将启 Act
我正在使用 Quartz 进行一个项目,并且一直存在与作业的依赖关系的问题。 我们有一个设置,其中 A 和 B 不相互依赖,但 C 是: A 和 B 可以同时运行,但 C 只能在 A 和 B 都完成的
JobDetail.requestsRecovery 的文档属性(property)声明如下 Instructs the Scheduler whether or not the Job should
我得到的调度程序如下: StdScheduler schedulerBean = (StdScheduler) ApplicationContextUtil.getBean(schedulerBean
我正在使用 CronTriggerBean 和 SimpleTriggerBean quartz 调度程序来执行触发器。执行触发器后永久不保存有关触发器的详细信息。在执行之前触发器数据被存储在执行之后
我在我的 .NETCore 服务器中使用 Serilog,并在我的云部署中使用多个接收器,例如控制台、文件和 Graylog (GELF)。 一旦我将日志级别设置为 DEBUG,我每隔几秒钟就会从 q
全部, 我们配置了一个 Quartz.net 调度器。其配置如下: 在分析数据库时,我们注意到以下流量每 23-27 秒执行一次: exec sp_executesql N'SELECT
目前我有一个代码,它有一个 java main 方法,它的执行需要很少的命令行参数。我正在将此作为 quartz 作业,我想将参数传递给这项工作。 有什么办法可以做到吗?我对 JobDataMap 进
我正在使用 Quartz Scheduler,有 15 个工作。对于每项工作,都有一个触发器。 我想为每个触发器设置优先级。我可以将低优先级设置为 10,将高优先级设置为 1。 但是因为我有 15 个
我正在使用 Quartz 框架,对时间生成有点困惑。这是一个简单的代码,它在上午 11:30 生成每日触发器。为了测试这一点,我使用 ComputeFireTimes 查询生成了接下来的 100 个连
我正在使用 Quartz 调度,更具体地说是一个设置为每周每天晚上 10 点醒来的 cron 触发器。 我接触的另一个小组正在询问调度程序在一天中将唤醒多少次以检查它是否需要运行作业。晚上 10 点作
我们有一个托管在 IIS 8.0 上的 Intranet 应用程序。 我们有一些可用的网络方法需要在特定时间执行。 因此,我们使用了 Quartz 调度程序来调度执行 Web 方法的作业。在 glob
我有一个 quartz 作业,每天下午 3 点(服务器时间)运行。我想做的是让它在下午 3 点运行,但针对美国的每个时区。 quartz 作业会触发一封电子邮件给我的用户,我希望每个人都能在他们的时间
我正在尝试在我的 web 项目中使用 Quartz.net。我这样配置我的应用程序: CRMMoreThanOneJob jobGroup1 ReportingPortalBLL.Job
我们有 2 个应用程序使用 quartz 进行调度。我们应用程序的 quartz.properties 如下: org.quartz.scheduler.instanceName = sr22Quar
我有一些关于 Quartz 集群的问题,特别是关于触发器如何在集群内执行。 在执行作业时,quartz 是否对节点有任何偏好?例如总是或从不上次执行相同作业的节点,或者只是哪个节点首先执行作业? 是否
我记得我们不能终止当前正在运行的 Quartz Job,但我们可以中断并在必要时进行 bool 检查,是否需要进一步进行后续操作。 即使我们实现 InterruptableJob并调用schedule
我已经执行了 2 个作业( MyJob1 和 MyJob2 ),如下所示: public async Task ScheduleJob() { await _jobManage
我是一名优秀的程序员,十分优秀!