首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

Quartz1.6有状态JOB碰到的棘手有关问题既解决方案

2012-06-27 
Quartz1.6有状态JOB碰到的棘手问题既解决方案?????? 关于Quartz,我想不要多做介绍了,凡是接触JAVA调度的都

Quartz1.6有状态JOB碰到的棘手问题既解决方案

?????? 关于Quartz,我想不要多做介绍了,凡是接触JAVA调度的都会知道这个开源的调度框架.本文就重点说下Quartz中有状态JOB的使用心得.因为我感觉国内的有状态JOB相关的资料比较少,所以在此提供一部分个人的一点经验.主要是针对使用quartz1.6的有状态JOB可能出现的一个棘手问题.

?????

1.关于有状态JOB(StatefulJob)

?

网上有很多关于有状态JOB的作用与使用的文章,我借鉴下,做下简单的说明:

a). 实现有状态JOB只需要实现org.quartz.StatefulJob 接口即可,StatefulJob 接口仅仅是扩展了 Job 接口,未加入新的方法.

?

b). Job(无状态)和 StatefulJob 在框架中使用中存在两个关键差异。首先,JobDataMap 在每次执行之后重新持久化到 JobStore 中。这样就确保你对 Job 数据的改变直到下次执行仍然保持着。你可以在有状态 Job 中简单的通过 map 的 put() 方法来修改 JobDataMap.已存在的任何数据会被新的数据覆盖掉。你也能对无状态的 Job 这么做,但是因为对于无状态 Job 来说,JobDataMap 不会持久化,所以数据不会保存下来。??

?????

c).? 两个或多个有状态的 JobDetail 实例不能并发执行。说的是你创建并注册了一个有状态 JobDetail 到 Scheduler 上。你还建立了两个 Trigger 来触发这个 Job:一个每五分钟触发,另一个也是每五分钏触发。假如这两个 Trigger 试图在同一时刻触发 Job,框架是不允许这种事情发生的。第二个 Trigger 一直会被阻塞直到第一个结束。

?

2.使用有状态JOB可能碰到的棘手问题(我目前所碰到的)

?? 在使用quartz1.6版本的时候,我碰到过比较麻烦的问题,后来在iteye和csdn求助都没有解决.还是从国外的文章上找到了一些眉目解决了.

??? 在实现SteafulJob接口后,该JOB怎么搞都只执行一次.

?

public class SimpleJob implements StatefulJob {        public void execute(JobExecutionContext context) throws JobExecutionException {            System.out.println("begin execute...");            System.out.println("end execute...");        } } 

?

public static void main(String [] args) {        try{           Scheduler scher = StdSchedulerFactory.getDefaultScheduler();      Calendar cal = Calendar.getInstace();           cal.add(Calendar.SECOND,1);           Trigger trigger = new SimpleTrigger("JD","JD",cal.getTime (),null,5,3000L);           JobDetail jobDetail = new JobDetail("JD","JD",SimpleJob.class);           scher.scheduleJob(jobDetaill,trigger);           scher.start();        }catch(Exception ex){             ex.printStackTrade();        } } 

?

?

?后来发现,每次调度启动执行一次后,quartz的记录触发器状态的表就会显示该触发器的状态为:ERROR.

于是从这上面下功夫,还是久久不能解决,然后求助网络.后来尝试了2个方案,终于解决了.

?

方案一: 国内网站的一个解决方案,说是2个或多个项目使用同一个quartz数据源,会产生冲突出现上述问题,突然想起公司的quartz数据源好像是有2-3个项目连着.结果修改了其他2个项目的quartz数据源,只让我正在弄的项目连接quartz数据源,一样没能解决,只能作罢.估计我出现的问题和这位总结者的问题不一样.

?

?

?

???

?

方案二:这是从国外网站看到的一个方案,属于换血型的改动,风险也还是有的.就是进行版本迁移.Quartz1.6及以下版本存在着一些不稳定的状况,具体什么状况我没验证过.但是我是实在不知道怎么下手了,就尝试着将Quartz换成方案中所说的稳定性很不错的版本:2.0版本.然后进行测试,问题就解决了.

?

Quartz2.0版本作为目前quartz最稳定的版本,还是值得使用的.不过中间的API变动相当大.我列出一些不同的地方.

?

a). 实现方式

2.0之前的版本是直接实现StatefulJob接口.

2.0版本:使用注解方式

@PersistJobDataAfterExecution @DisallowConcurrentExecution public class StatefulJobAction implements Job{ }

?

b). 对象操作

?

JobDetail jobDetail = null; JobDataMap dataMap = null; CronTrigger cronTrigger = null; String calendarName = triggerName; DailyCalendar dailCalendar = new DailyCalendar(startTime,endTime);dailyCalendar.setInvertTimeRange(true); scheduler.addCalendar(calendarName,dailyCalendar,null,null); /** quartz1.6 */ /** jobDetail = new JobDetail(jobName,jobGroup,StatefulJobAction.class); dataMap = new JobDataMap(); dataMap.put("Scher",scher); jobDetail.setJobDataMap(dataMap); cronTrigger = new CronTrigger(triggerName,triggerGroup); cronTrigger.setStartTime(startTime); cronTrigger.setEndTime(endTime); cronTrigger.setCalendarName(calendarName); */ /** quartz2.0 */ jobDetail = newJob(StatefulJobAction.class).withIdentity(jobName,jobGroup).build(); dataMap = jobDetail.getJobDataMap(); dataMap.put("Scher",scher); //一次性构建触发器 /** cronTrigger = newTrigger().withIdentity(triggerName,triggerGroup).withSchedule(cronSchedule(cronExpress)).startAt(startTime).endAt(endTime).modifiedByCalendar(triggerName).build; */ //分开构建触发器 TriggerBuilder<Trigger> triggerBuilder = newTrigger(); triggerBuilder.withIdentity(triggerName,triggerGroup);if(StringUtils.isBlank(startTime)){    triggerBuilder.startAt(new Date()); } else{     triggerBuilder.startAt(startTime); } triggerBuilder.endAt(endTime); cronTrigger = triggerBuilder.withSchedule(cronSchedule(cronExpress)).modifiedByCalendar(triggerName).build(); //简单触发器 // SimpleTrigger simpleTrigger = newTrigger().withSchedule(simpleSchedule()).withIntervalInSeconds(10).withRepeatCount(5).build(); 

?

另外有一点需要注意,可以看到quartz2.0版本有很多这种写法:newTrigger(),simpleScheduler().其实是采用了JDK1.5后提供的静态导入.

import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob;import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger;

?

?import static静态导入是JDK1.5中的新特性。静态导入是导入这个类里的静态方法。然后就可以直接用方法名调用静态方法,而不必用ClassName.方法名 的方式来调用。

这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(...);就可以将其写入一个静态方法print(...),在使用时直接print(...)就可以了。

?

?

最后在附件里附上quartz2.0需要的jar包,和quartz2.0的docs即sql脚本.

必须的JAR包:

quartz-2.0.jar,

slf4j-api.1.6.2.jar

slf4j-log4j12-1.6.2.jar

c3p0-0.9.1.jar

热点排行