文档章节

使用Quartz作为任务调度时 fireTime的一个坑

caiw
 caiw
发布于 2015/02/01 16:53
字数 867
阅读 52
收藏 0

         一个任务调度的业务场景:需要在每个小时后2秒钟从数据库中取得当前小时的数据并进行计算,此时使用Quartz做为任务调度,设置每个小时执行一次,sleep2秒以后执行业务代码。并使用Quartz提供的fireTime作为时间条件获取数据。

先看示例代码:

public class QuartzTest {
	public static void main(String[] args) throws SchedulerException {
		//String cron="00 00 * * * ?";
		//为了测试使用就近时间。
		String cron="00 17 * * * ?";
		StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory(); 
		Scheduler stdSchedulerFactory=sf.getScheduler();
	       //50个任务
		for(int i=1;i<50;i++){
			JobDetail jobDetail=JobBuilder.newJob(Job1.class).build();
			Trigger trigger=TriggerBuilder.newTrigger()
					.withSchedule(CronScheduleBuilder.cronSchedule(cron))
					.build();
			sched.scheduleJob(jobDetail,trigger);
		}
		sched.start();
	}

}

Job1.class

public class Job1  implements Job{
	public void execute(JobExecutionContext context)
			throws JobExecutionException {
		SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		String dateStr=sf.format(context.getFireTime());
		//记录任务调度的时间
		System.out.println(dateStr);
		try {
		    Thread.sleep(2000);
	            //do someting  with dateStr.... 
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

得到的结果:

2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:00
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:01
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:02
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:03
2015-02-01 04:27:04
2015-02-01 04:27:04
2015-02-01 04:27:04
2015-02-01 04:27:04
2015-02-01 04:27:04
2015-02-01 04:27:04
2015-02-01 04:27:04
2015-02-01 04:27:04
2015-02-01 04:27:04

通过结果发现 拿到的fireTime和预期不一样。

这个时候如果使用fireTime去获取数据就会拿到有误差的数据,也会造成业务结果错误。

通过分析发现 Quartz(v2.1.1) 默认使用的是自带线程池的实现:SimpleThreadPool,并且默认为10个线程,在并发任务达到 10 个以后,再有触发的任务就无法被执行了,只能等待有空闲线程的时候才能得到执,这也是为什么结果中只有前10个结果是符合预期的。

我们可以添加配置文件来修改Quartz的一些默认配置项,并发数:

org.quartz.threadPool.threadCount=50;

也可以直接在代码中修改:

StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory(); 
Properties pro=new Properties();
pro.setProperty("org.quartz.threadPool.threadCount", "50");
stdSchedulerFactory.initialize(pro);

 但是必须指出一点,这个初始线程数并不是越大越好。当并发线程太多时,系统整体性能反而会下降,因为系统把很多时间花在了线程调度上。

© 著作权归作者所有

共有 人打赏支持
caiw
粉丝 2
博文 15
码字总数 5222
作品 0
成都
Quartz任务调度源码分析

从源码分析中可以看出,任务的整个调度过程为,初始化线程池,及调度器QuartzScheduler,然后由线程池去执行QuartzSchedulerThread,将触发器任务(job与触发器)添加到存储器(TreeSet,timeT...

sgkbkega
2016/09/08
17
0
如何高效排查日均调度量超两百万次的重复调度问题? | 技术头条

作者 | 余慧娟 责编 | 郭芮 系统自从改用Quartz做任务调度后,一日的调度量均在两百万次以上。随着调度量的增加,突然开始出现job重复调度的情况,且没有规律可循。网上也没有说得较为清楚的...

CSDN资讯
09/09
0
0
基于 Quartz 开发企业级任务调度应用

简介: Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。作为一个优秀的开源调度框架,Quartz 具有功能强大,应用灵活,易于集成的特点。本文剖析了 Qu...

IBMdW
2013/05/19
12.9K
29
quartz集群

其实主要还是借鉴别人的东东,写的还挺好的。我自己只在最后说说自己遇到的坑吧。 1、Quartz任务调度的基本实现原理   Quartz是OpenSymphony开源组织在任务调度领域的一个开源项目,完全基...

梦蝶飘雪
2016/08/12
188
0
基于quartz的云调度中心实现

一、背景 作为业务开发人员,会经常需要写一个定时任务。目前,写定时任务应用最广泛最成熟的方案是OpenSymphony开源组织在任务调度领域的一个开源项目quartz,比如要写一个定时数据同步任务...

zjytk05
2016/05/19
0
33

没有更多内容

加载失败,请刷新页面

加载更多

Bash各类扩展详解

Bash各类扩展详解 Bash中主要包括大括号扩展、波浪号扩展、变量扩展、子命令扩展、文件名扩展和算数扩展。这些扩展组合在一起为Bash带来了极大的易用性。掌握这些扩展的用法和功能,能够为B...

小陶小陶
52分钟前
1
0
EventBus原理深度解析

一、问题描述 在工作中,经常会遇见使用异步的方式来发送事件,或者触发另外一个动作:经常用到的框架是MQ(分布式方式通知)。如果是同一个jvm里面通知的话,就可以使用EventBus。由于Event...

yangjianzhou
今天
5
0
OpenCV图像处理实例:libuv+cvui显示摄像头视频

#include <iostream>#include <opencv2/opencv.hpp>#define CVUI_IMPLEMENTATION#include <cvui.h>extern "C"{#include <uv.h>}using namespace std;#define WINDOW_NAM......

IOTService
今天
3
0
openJDK之JDK9的String

1.openJDK8的String 先来看下openJDK8的String的底层,如下图1.1所示: 图1.1 底层上使用的是char[],即char数组 每个char占16个bit,Character.SIZE的值是16。 2.openJDK9中的String 图2.1...

克虏伯
今天
3
0
UEFI 模式下如何安装 Ubuntu 16.04

作者:知乎用户 链接:https://www.zhihu.com/question/52092661/answer/259583475 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 针对UEFI模式下安装U...

寻知者
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部