我正在转换我的Tomcat应用程序以使用Quartz调度程序。我主要用它来触发后台的电子邮件进程,我担心处理器会出现并发作业。所以这是一个最佳实践问题。
问)产生一个石英作业(例如每小时)并让它连续调用几个例程是否更好?这样,例程2将在例程1完成之前启动。
或者最好将每个例程安排为单独的Quartz作业并限制线程数?
如果有更多作业安排线程可用,会发生什么。他们只是排队吗?即可以是我的控制机制。我已经使用指令来防止并发相同的工作。
我不希望同时运行三个类似的作业。它不依赖于时间,因此在处理器上更容易连接。
最直接的架构是什么?
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class HourJob implements Job, InterruptableJob {
boolean interrupted = false;
String cls = this.getClass().getName();
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println(cls+"-Start");
for(int i=1; i<15; i++){
try { //do work
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(interrupted){
System.out.println(cls+"-Interrupted");
return;
}
}//for
System.out.println(cls+"-Exit");
}
@Override
public void interrupt() throws UnableToInterruptJobException {
interrupted = true;
}
}
和
public void contextInitialized(ServletContextEvent event) {
...
sched = schedFact.getScheduler();
sched.start();
JobDetail hourJob = newJob(HourJob.class ).withIdentity("hourJob", "group1").build();
Trigger hourTrig = newTrigger()
.withIdentity("hourTrig", "group1")
.withSchedule(cronSchedule("0 0 * * * ?")).build();
sched.scheduleJob(hourJob, hourTrig);
和
public void contextDestroyed(ServletContextEvent event) {
...
for(JobExecutionContext job : sched.getCurrentlyExecutingJobs()){
JobKey jK = job.getJobDetail().getKey();
System.out.printf("Inerrupting %s\n", jK.getName());
sched.interrupt(jK);
}
sched.shutdown(true);
答案 0 :(得分:1)
如果你只有一些工作每天开几次,那么一个 线程很充足。如果你有成千上万的工作,有很多 每分钟开火,然后你想要一个更像50或100的线程数 (这在很大程度上取决于你的工作所做的工作的性质, 和您的系统资源
因此,您只能使用一个线程,并安排您的作业使用单独的计划执行,以便它们不会同时触发所有。
如果持久触发器错过其触发时间,则会发生失火 因为调度程序正在关闭,或者因为没有 Quartz的线程池中可用的线程,用于执行作业。
请注意,您可以通过更改默认失火阈值(30秒)来配置触发器配置错误的时间。如果线程在该阈值之前变为可用,则触发器将执行而不会被视为失效。另一方面,关于失火的触发器,失火策略决定了将会发生什么:
不同的触发类型具有不同的失火指令 可供他们使用。默认情况下,他们使用智能策略&#39;指示 - 它具有基于触发器类型和配置的动态行为。 当调度程序启动时,它会搜索任何持久触发器 那些已经失误,然后根据他们的情况更新每一个 单独配置的失火指令。
默认策略对于每种类型的触发器都是不同的,但是一旦线程可用,它通常会运行错过的触发器。在任何情况下,您都需要查看您使用的触发器的策略,并将其更改为您想要的触发器
答案 1 :(得分:0)
这是间接答案,但这就是我们所做的:
由于我们使用Quartz来安排许多类型的任务,我们并不希望某项工作占用大量资源,从而影响其他工作。
所以我们最终分裂了这个过程:
* Quartz作业只是将数据推送到作业队列(每个作业类型不同)
*我们配置执行服务(轻松扩展)从队列中读取并执行实际工作(无论是发送电子邮件还是其他批处理操作)。
我们现在有超过数千个作业在没有并发问题的情况下运行,并且能够轻松扩展每种作业类型