quartz的maven依赖_spring-boot-quartz, 依赖spring-boot-parent good

/**

*

state的值代表该任务触发器的状态:

STATE_BLOCKED 4 // 运行

STATE_COMPLETE 2 //完成那一刻,不过一般不用这个判断Job状态

STATE_ERROR 3 // 错误

STATE_NONE -1 //未知

STATE_NORMAL 0 //正常无任务,用这个判断Job是否在运行

STATE_PAUSED 1 //暂停状态

*/

importjava.util.Date;importorg.quartz.CronTrigger;importorg.quartz.JobDetail;importorg.quartz.Scheduler;importorg.quartz.SchedulerException;importorg.quartz.SchedulerFactory;importorg.quartz.SimpleTrigger;importorg.quartz.Trigger;importorg.quartz.impl.StdScheduler;importorg.quartz.impl.StdSchedulerFactory;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.context.ApplicationContext;importorg.springframework.scheduling.quartz.SchedulerFactoryBean;importcn.wa8.qweb.extract.action.Extract2DB;public classSimpleRun {private static Logger log = LoggerFactory.getLogger(SimpleRun.class);public void run() throwsException {

SchedulerFactory schedFact= neworg.quartz.impl.StdSchedulerFactory();

Scheduler sched=schedFact.getScheduler();

JobDetail jobDetail= new JobDetail("myJob",null,SimpleJob.class);

SimpleTrigger trigger= new SimpleTrigger("myTrigger",null,newDate(),null,

SimpleTrigger.REPEAT_INDEFINITELY,30L * 1000L);

sched.scheduleJob(jobDetail, trigger);//sched.addJobListener(new MyTriggerListener());

SimpleJob.preDate = newDate();

sched.start();

System.out.println("starting");/***

state的值代表该任务触发器的状态:

STATE_BLOCKED 4 // 运行

STATE_COMPLETE 2 //完成那一刻,不过一般不用这个判断Job状态

STATE_ERROR 3 // 错误

STATE_NONE -1 //未知

STATE_NORMAL 0 //正常无任务,用这个判断Job是否在运行

STATE_PAUSED 1 //暂停状态*/

while (true){if(4 == sched.getTriggerState("myTrigger", null)){

System.out.println("running");

}else if(0 == sched.getTriggerState("myTrigger", null)){

System.out.println("ending");

}else{

System.out.println("error state:"+sched.getTriggerState("myTrigger", null));

}try{

Thread.sleep(5*1000);

}catch(Exception e) {//TODO: handle exception

}

}

}public static voidmain(String[] args) {

SimpleRun simpleRun= newSimpleRun();try{

simpleRun.run();

}catch(Exception e) {

e.printStackTrace();

}

}

}

importjava.util.Date;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importcn.wa8.qweb.extract.action.Extract2DB;importorg.quartz.Job;importorg.quartz.JobExecutionContext;importorg.quartz.JobExecutionException;importorg.quartz.StatefulJob;/*Extract2DB extract2db = new Extract2DB();

extract2db.CommonBaseExtract();*/

public class SimpleJob implementsStatefulJob{public staticDate preDate ;public void execute(JobExecutionContext arg0) throwsJobExecutionException {

System.out.println("into Job");

Date currentDate= newDate();

Long s= (currentDate.getTime()-preDate.getTime())/1000;try{

Thread.sleep(10*1000);

}catch(Exception e) {

e.printStackTrace();

}

System.out.println(s);

System.out.println("leave Job:"+Thread.currentThread().toString());

preDate=currentDate;

}

}

http://blog.csdn.net/u010666884/article/details/51842610

都是执行时间大于间隔时间才会出现的情况,实际做了测试和http://blog.sina.com.cn/s/blog_56d8ea900100cecq.html第2点有点不符,记录如下:

第一种情况:misfire设置时间为600秒;任务每隔2分钟执行一次;任务执行时间为3分钟;

上次执行时间 下次执行时间 状态 解释

20:23:04 20:25:04 正在执行 任务实际要执行到20:26:04,推后两分钟是20:28:04

时间到了20:26:04。日志变更为:

20:25:04 20:27:04 正在执行 任务实际要执行的20:29:04,推后两分钟是20:31:04

时间到了20:29:04,日志变更为:

20:27:04 20:29:04

连续三次发现,实际开始的时间减去应该开始的时间差是递增的;上次执行和下次执行时间反映的实际情况都是不准确的,而且会出现下次执行时间小于当前时间的情况。

注意:持续执行的到 实际启动时间 减去 应该开始时间 大于等于misfire时间;奇怪的是,不是开始参考第二种情况继续执行,而是最后一次执行后即开始长时间等待,而且上次以及下次开始时间也不更新,保持原样;直到实际启动时间+misfire时间 时刻开始继续执行,并且更新上次以及下次开始时间,再开始一个上述周期。

第二种情况:misfire设置时间为6秒,任务每隔2分钟执行一次,任务执行时间为3分钟:

上次执行时间 下次执行时间 状态 解释

18:08:12 18:10:12 正在执行 任务实际要执行到18:11:12,推后两分钟是18:13:12

时间到了18:11:12,日志变更为:

18:08:12 18:10:12 等待 超出misfire时间;任务还没有更新状态

18:08:12 18:12:12 等待 是18:12:12,而不是18:13:12。

算法描述如下:

本次任务应该开始时间为18:10:12,应该结束时间为18:12:12;实际启动时间为18:11:12;实际启动后结束时间为18:13:12;实际启动时间减去应该开始时间超出了misfire,所以状态为等待,即本次任务不执行,从而上次执行时间不变;

计算下次执行时间:当前时间为18:11:12(或者一个稍微大于该值的值),拿应该结束时间以及实际启动后结束时间和当前时间比较,取当前时间往后的最小值作为下次任务启动时间。(算法兼容下面第2点说法)

18:12:12 18:14:12 正在执行

其他引用:

org.quartz.jobStore.misfireThreshold = 60000 #60秒 默认值

那么执行第一次作业是在10:01秒,这时会设定下一次的执行时间为10:02秒,要等一个作业执行完之后才有可用线程,大概要在10:11秒才能执行前面安排的应该在10:02执行的作业,这时就会用到misfireThreshold, 因为10:11与10:02之间的差值小于6000,所以执行该作业,并以10:02为基准设置下一次执行时间为10:03,这样造成每次实际执行时间与安排时间错位

如果 org.quartz.jobStore.misfireThreshold = 6000 #秒

同样,在10:11计划执行安排在10:02的作业,发现10:11与10:02之间的差值小于6000,那么直接跳过该作业,执行本应在当前时间执行的 作业,这时候会以10:11为基准设定下次作业执行时间为10:12(状态此段区间内一直是等待,只是更改了下次作业时间)

其他情况:

quartz有个全局的参数misfireThreshold设置可以允许的超时时间,超过了就不执行,未超过就执行。

比如设置了misfireThreshold=30分钟,如果一个任务定时在10:30执行,但在10:29服务器挂了,在10:50启动,虽然任务超时了21分钟,但小于misfireThreshold,所以还是可以执行。

而如果服务器11:10才启动,那就misfire了。

对于周期性的任务,如果有misfire的情况出现,则会自动更新CronTrigger的时间周期

默认情况下会在当前时间马上执行前一个被misfire的任务

而如果设置MISFIRE_INSTRUCTION_DO_NOTHING,则不对misfire的任务做特殊处理,只从当前时间之后的下一次正常调度时间开始执行

http://blog.sina.com.cn/s/blog_56d8ea900101d2mh.html

http://www.quartz-scheduler.org/documentation/quartz-2.1.x/quick-start.html

spring-boot-quartz, 依赖spring-boot-parent

application.properties

# IDENTITY (ContextIdApplicationContextInitializer)

spring.application.index=WebQuartz.v1.1

spring.application.name=WebQuartz

#Server

server.port=80

server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServlet

security.basic.enabled=false

management.security.enabled=false

#MVC

spring.mvc.view.prefix=/WEB-INF/views/

spring.resources.static-locations=classpath:/static/

security.basic.enabled=false

management.security.enabled=false

#LOG

logging.config=classpath:log4j2.xml

configuration

@Configuration

public class QuartzConfig {

@Bean

public Scheduler scheduler() throws IOException, SchedulerException {

SchedulerFactory schedulerFactory = new StdSchedulerFactory(quartzProperties());

Scheduler scheduler = schedulerFactory.getScheduler();

scheduler.start();

return scheduler;

}

/**

* 设置quartz属性

* @throws IOException

* 2016年10月8日下午2:39:05

*/

public Properties quartzProperties() throws IOException {

Properties prop = new Properties();

prop.put("quartz.scheduler.instanceName", "ServerScheduler");

prop.put("org.quartz.scheduler.instanceId", "AUTO");

prop.put("org.quartz.scheduler.skipUpdateCheck", "true");

prop.put("org.quartz.scheduler.instanceId", "NON_CLUSTERED");

prop.put("org.quartz.scheduler.jobFactory.class", "org.quartz.simpl.SimpleJobFactory");

prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");

prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");

prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");

prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");

prop.put("org.quartz.jobStore.isClustered", "true");

prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");

prop.put("org.quartz.threadPool.threadCount", "5");

prop.put("org.quartz.dataSource.quartzDataSource.driver", "com.mysql.jdbc.Driver");

prop.put("org.quartz.dataSource.quartzDataSource.URL", "jdbc:mysql://localhost:3306/demo-schema");

prop.put("org.quartz.dataSource.quartzDataSource.user", "root");

prop.put("org.quartz.dataSource.quartzDataSource.password", "123456");

prop.put("org.quartz.dataSource.quartzDataSource.maxConnections", "10");

return prop;

}

}

JS

@Service

public class TaskServiceImpl {

private Logger logger = LogManager.getLogger(getClass());

@Autowired

private Scheduler scheduler;

/**

* 所有任务列表

* 2016年10月9日上午11:16:59

*/

public List list(){

List list = new ArrayList<>();

try {

for(String groupJob: scheduler.getJobGroupNames()){

for(JobKey jobKey: scheduler.getJobKeys(GroupMatcher.groupEquals(groupJob))){

List extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);

for (Trigger trigger: triggers) {

Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());

JobDetail jobDetail = scheduler.getJobDetail(jobKey);

String cronExpression = "", createTime = "";

if (trigger instanceof CronTrigger) {

CronTrigger cronTrigger = (CronTrigger) trigger;

cronExpression = cronTrigger.getCronExpression();

createTime = cronTrigger.getDescription();

}

TaskInfo info = new TaskInfo();

info.setJobName(jobKey.getName());

info.setJobGroup(jobKey.getGroup());

info.setJobDescription(jobDetail.getDescription());

info.setJobStatus(triggerState.name());

info.setCronExpression(cronExpression);

info.setCreateTime(createTime);

list.add(info);

}

}

}

} catch (SchedulerException e) {

e.printStackTrace();

}

return list;

}

/**

* 保存定时任务

* @param info

* 2016年10月9日上午11:30:40

*/

@SuppressWarnings("unchecked")

public void addJob(TaskInfo info) {

String jobName = info.getJobName(),

jobGroup = info.getJobGroup(),

cronExpression = info.getCronExpression(),

jobDescription = info.getJobDescription(),

createTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");

try {

if (checkExists(jobName, jobGroup)) {

logger.info("===> AddJob fail, job already exist, jobGroup:{}, jobName:{}", jobGroup, jobName);

throw new ServiceException(String.format("Job已经存在, jobName:{%s},jobGroup:{%s}", jobName, jobGroup));

}

TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

JobKey jobKey = JobKey.jobKey(jobName, jobGroup);

CronScheduleBuilder schedBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();

CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withDescription(createTime).withSchedule(schedBuilder).build();

Class extends Job> clazz = (Class extends Job>)Class.forName(jobName);

JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(jobKey).withDescription(jobDescription).build();

scheduler.scheduleJob(jobDetail, trigger);

} catch (SchedulerException | ClassNotFoundException e) {

throw new ServiceException("类名不存在或执行表达式错误");

}

}

/**

* 修改定时任务

* @param info

* 2016年10月9日下午2:20:07

*/

public void edit(TaskInfo info) {

String jobName = info.getJobName(),

jobGroup = info.getJobGroup(),

cronExpression = info.getCronExpression(),

jobDescription = info.getJobDescription(),

createTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");

try {

if (!checkExists(jobName, jobGroup)) {

throw new ServiceException(String.format("Job不存在, jobName:{%s},jobGroup:{%s}", jobName, jobGroup));

}

TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

JobKey jobKey = new JobKey(jobName, jobGroup);

CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();

CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withDescription(createTime).withSchedule(cronScheduleBuilder).build();

JobDetail jobDetail

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值