Quartz定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行, 如果定时任执行太长,会长时间占用资源,导致其它任务堵塞。
1.在Spring中这时需要设置concurrent的值为false, 禁止并发执行。

 <property name="concurrent" value="true" />

2.当不使用spring的时候就需要在Job的实现类上加@DisallowConcurrentExecution的注释
@DisallowConcurrentExecution 禁止并发执行多个相同定义的JobDetail, 这个注解是加在Job类上的, 但意思并不是不能同时执行多个Job, 而是不能并发执行同一个Job Definition(由JobDetail定义), 但是可以同时执行多个不同的JobDetail, 举例说明,我们有一个Job类,叫做SayHelloJob, 并在这个Job上加了这个注解, 然后在这个Job上定义了很多个JobDetail, 如sayHelloToJoeJobDetail, sayHelloToMikeJobDetail, 那么当scheduler启动时, 不会并发执行多个sayHelloToJoeJobDetail或者sayHelloToMikeJobDetail, 但可以同时执行sayHelloToJoeJobDetail跟sayHelloToMikeJobDetail

@PersistJobDataAfterExecution 同样, 也是加在Job上,表示当正常执行完Job后, JobDataMap中的数据应该被改动, 以被下一次调用时用。当使用@PersistJobDataAfterExecution 注解时, 为了避免并发时, 存储数据造成混乱, 强烈建议把@DisallowConcurrentExecution注解也加上。

@DisallowConcurrentExecution

此标记用在实现Job的类上面,意思是不允许并发执行,按照我之前的理解是 不允许调度框架在同一时刻调用Job类,后来经过测试发现并不是这样,而是Job(任务)的执行时间[比如需要10秒]大于任务的时间间隔[Interval(5秒)],那么默认情况下,调度框架为了能让 任务按照我们预定的时间间隔执行,会马上启用新的线程执行任务。否则的话会等待任务执行完毕以后 再重新执行!(这样会导致任务的执行不是按照我们预先定义的时间间隔执行)

测试代码,这是官方提供的例子。设定的时间间隔为3秒,但job执行时间是5秒,设置@DisallowConcurrentExecution以后程序会等任务执行完毕以后再去执行,否则会在3秒时再启用新的线程执行

org.quartz.threadPool.threadCount = 5 这里配置框架的线程池中线程的数量,要多配置几个,否则@DisallowConcurrentExecution不起作用
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 5
org.quartz.jobStore.class =org.quartz.simpl.RAMJobStore
/*
* Copyright 2005 - 2009 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/ package org.quartz.examples.example5; import java.util.Date; import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution; /**
* <p> A dumb implementation of Job, for unit testing purposes. </p>
*
* @author James House
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class StatefulDumbJob implements Job { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Constants.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public static final String NUM_EXECUTIONS = "NumExecutions"; public static final String EXECUTION_DELAY = "ExecutionDelay"; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Constructors.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public StatefulDumbJob() {
} /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Interface.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /**
* <p> Called by the <code>{@link org.quartz.Scheduler}</code> when a <code>{@link org.quartz.Trigger}</code> fires that is associated with the <code>Job</code>. </p>
*
* @throws JobExecutionException if there is an exception while executing the job.
*/
public void execute(JobExecutionContext context) throws JobExecutionException {
System.err.println("---" + context.getJobDetail().getKey() + " executing.[" + new Date() + "]"); JobDataMap map = context.getJobDetail().getJobDataMap(); int executeCount = 0;
if (map.containsKey(NUM_EXECUTIONS)) {
executeCount = map.getInt(NUM_EXECUTIONS);
} executeCount++; map.put(NUM_EXECUTIONS, executeCount); long delay = 5000l;
if (map.containsKey(EXECUTION_DELAY)) {
delay = map.getLong(EXECUTION_DELAY);
} try {
Thread.sleep(delay);
} catch (Exception ignore) {
} System.err.println(" -" + context.getJobDetail().getKey() + " complete (" + executeCount + ")."); } }
/*
* Copyright 2005 - 2009 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/ package org.quartz.examples.example5; import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.DateBuilder.*; import java.util.Date; import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* Demonstrates the behavior of <code>StatefulJob</code>s, as well as how misfire instructions affect the firings of triggers of <code>StatefulJob</code> s - when the jobs take longer to execute that the frequency of the trigger's repitition.
*
* <p> While the example is running, you should note that there are two triggers with identical schedules, firing identical jobs. The triggers "want" to fire every 3 seconds, but the jobs take 10 seconds to execute. Therefore, by the time the jobs complete their execution, the triggers have already "misfired" (unless the scheduler's "misfire threshold" has been set to more than 7 seconds). You should see that one of the jobs has its misfire instruction set to <code>SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</code>, which causes it to fire immediately, when the misfire is detected. The other trigger uses the default "smart policy" misfire instruction, which causes the trigger to advance to its next fire time (skipping those that it has missed) - so that it does not refire immediately, but rather at the next scheduled time. </p>
*
* @author <a href="mailto:bonhamcm@thirdeyeconsulting.com">Chris Bonham</a>
*/
public class MisfireExample {
public void run() throws Exception {
Logger log = LoggerFactory.getLogger(MisfireExample.class); log.info("------- Initializing -------------------"); // First we must get a reference to a scheduler
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler(); log.info("------- Initialization Complete -----------"); log.info("------- Scheduling Jobs -----------"); // jobs can be scheduled before start() has been called // get a "nice round" time a few seconds in the future...
Date startTime = nextGivenSecondDate(null, 15); // statefulJob1 will run every three seconds
// (but it will delay for ten seconds)
JobDetail job = newJob(StatefulDumbJob.class).withIdentity("statefulJob1", "group1").usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build(); SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime).withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()).build(); Date ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every " + trigger.getRepeatInterval() / 1000 + " seconds"); log.info("------- Starting Scheduler ----------------"); // jobs don't start firing until start() has been called...
sched.start(); log.info("------- Started Scheduler -----------------"); try {
// sleep for ten minutes for triggers to file....
Thread.sleep(600L * 1000L);
} catch (Exception e) {
} log.info("------- Shutting Down ---------------------"); sched.shutdown(true); log.info("------- Shutdown Complete -----------------"); SchedulerMetaData metaData = sched.getMetaData();
log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
} public static void main(String[] args) throws Exception { MisfireExample example = new MisfireExample();
example.run();
} }

@PersistJobDataAfterExecution

此标记说明在执行完Job的execution方法后保存JobDataMap当中固定数据,在默认情况下 也就是没有设置 @PersistJobDataAfterExecution的时候 每个job都拥有独立JobDataMap

否则改任务在重复执行的时候具有相同的JobDataMap

/*
* Copyright 2005 - 2009 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/ package com.quartz.demo.example6; import java.util.Date; import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.PersistJobDataAfterExecution; @PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class BadJob1 implements Job { public BadJob1() {
} public void execute(JobExecutionContext context) throws JobExecutionException {
JobKey jobKey = context.getJobDetail().getKey();
JobDataMap dataMap = context.getJobDetail().getJobDataMap(); int denominator = dataMap.getInt("denominator");
System.out.println("---" + jobKey + " executing at " + new Date() + " with denominator " + denominator); denominator++;
dataMap.put("denominator", denominator);
} }
/*
* Copyright 2005 - 2009 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/ package com.quartz.demo.example6; import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.DateBuilder.*; import java.util.Date; import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory; public class JobExceptionExample { public void run() throws Exception { // First we must get a reference to a scheduler
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler(); // jobs can be scheduled before start() has been called // get a "nice round" time a few seconds in the future...
Date startTime = nextGivenSecondDate(null, 2); JobDetail job = newJob(BadJob1.class).withIdentity("badJob1", "group1").usingJobData("denominator", "0").build(); SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime).withSchedule(simpleSchedule().withIntervalInSeconds(2).repeatForever()).build(); Date ft = sched.scheduleJob(job, trigger); //任务每2秒执行一次 那么在BadJob1的方法中拿到的JobDataMap的数据是共享的.
//这里要注意一个情况: 就是JobDataMap的数据共享只针对一个BadJob1任务。
//如果在下面在新增加一个任务 那么他们之间是不共享的 比如下面 JobDetail job2 = newJob(BadJob1.class).withIdentity("badJob1", "group1").usingJobData("denominator", "0").build(); SimpleTrigger trigger2 = newTrigger().withIdentity("trigger1", "group1").startAt(startTime).withSchedule(simpleSchedule().withIntervalInSeconds(2).repeatForever()).build(); //这个job2与job执行的JobDataMap不共享
sched.scheduleJob(job2, trigger2); sched.start(); try {
// sleep for 30 seconds
Thread.sleep(30L * 1000L);
} catch (Exception e) {
} sched.shutdown(false);
} public static void main(String[] args) throws Exception { JobExceptionExample example = new JobExceptionExample();
example.run();
} }

Quartz 并发/单线程的更多相关文章

  1. Spring集成的Quartz 并发

    以前经常在任务调度程序中使用Spring集成的Quartz,这种方式可以用简单的声明式配置即可实现定时任务,并结合了Spring自身的Bean的管理功能,非常方便.配置样本如下: <bean i ...

  2. 线程回调,线程中的队列,事件,greenlet模块,gevent模块,自定义补丁, 单线程实现并发,协程

    1.线程回调 在线程池/进程池每次提交任务,都会返回一个表示任务的对象,Future对象Future对象具备一个绑定方法,add_done_callback 用于指定回调函数 add 意味着可以添加多 ...

  3. python并发学习总结

    目录 一.理解操作系统 二.任务类型 三.Socket模块 四.一个简单的C/S程序 五.使用阻塞IO实现并发 方案一:阻塞IO+多进程 方案二:阻塞IO+多线程 阻塞IO模型的思考和总结 六.使用非 ...

  4. Java并发容器篇

    作者:汤圆 个人博客:javalover.cc 前言 断断续续一个多月,也写了十几篇原创文章,感觉真的很不一样: 不能说技术有很大的进步,但是想法确实跟以前有所不同: 还没开始的时候,想着要学的东西太 ...

  5. python笔记-10(socket提升、paramiko、线程、进程、协程、同步IO、异步IO)

    一.socket提升 1.熟悉socket.socket()中的省略部分 socket.socket(AF.INET,socket.SOCK_STREAM) 2.send与recv发送大文件时对于黏包 ...

  6. Python IO 多路复用 \协程

    IO 多路复用 作用:  检测多个socket是否已经发生变化(是否已经连接成功/是否已经获取数据) 即(可读/可写) IO请求时 解决并发  :  单线程 def get_data(key): cl ...

  7. IO多路复用,协程

    https://www.cnblogs.com/wangjun187197/p/9642429.html Python之路--协程/IO多路复用 I/O复用模型 此模型用到select和poll函数, ...

  8. 协程--gevent模块(单线程高并发)

    先恶补一下知识点,上节回顾 上下文切换:当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行.这种 ...

  9. quartz集群分布式(并发)部署解决方案-Spring

    项目中使用分布式并发部署定时任务,多台跨JVM,按照常理逻辑每个JVM的定时任务会各自运行,这样就会存在问题,多台分布式JVM机器的应用服务同时干活,一个是加重服务负担,另外一个是存在严重的逻辑问题, ...

随机推荐

  1. JavaScript中使用console调试程序的坑

    上DEMO a = {key1: [1, 2], 'key2': {'key4': '11'}, 'key3': [1, 2]} console.info(1,a) a.key2.key4 = '22 ...

  2. 《.NET简单企业应用》项目开发环境

    项目开始,开发团队需要构建一套开发环境,主要包含:开发工具.代码管理/版本控制系统.任务和Bug管理系统和持续集成(CI)系统.本文主要列举项目开发中经常使用的开发工具和第三方库. 本文所列工具根据前 ...

  3. 如何参与linux 内核开发

    如果想评论或更新本文的内容,请直接联系原文档的维护者.如果你使用英文 交流有困难的话,也可以向中文版维护者求助.如果本翻译更新不及时或者翻 译存在问题,请联系中文版维护者.   英文版维护者: Gre ...

  4. hadoop的核心思想

    hadoop的核心思想 1.1.1. hadoop的核心思想 Hadoop包括两大核心,分布式存储系统和分布式计算系统. 1.1.1.1. 分布式存储 为什么数据需要存储在分布式的系统中哪,难道单一的 ...

  5. ubuntu14.04 安装matlab r2013a

    神奇的linux. 进入主题:matlab相信是不少工程人员缺少不了的工具,就我所在的通信行业更是如此,matlab的linux版本是和windows版本同步更新, 不过r2012之后只提供64位版本 ...

  6. Cookie 获取

    二级域名可以获取一级域名的Cookie值 二级域名下删除顶级域名下的Cookie,需要添加顶级域名的Cookie作用域 /// <summary> /// 根据cookie名称删除 /// ...

  7. 如何在cocos2dx lua的回调函数里面用self

    回调里的self是另一个不同的东西了,通常是触发回调的对象,或_G或nil ,视情况而定 我的 print(self) 输出 userdata function MyClass:sayFromCall ...

  8. Module模式 - 深入了解Javascript

    /* Modelu模式 优点:效率高,代码少,加载速度快,松耦合允许并行加载,提升下载速度 缺点:初始化时间久一点 */ //一.基础用法 var calculate = function (eq) ...

  9. Sql例子Sp_ExecuteSql 带参数

    Declare @i int, @projectCount int ) --参数 ) ) ) ) ) ) --循环变量起始 --得到所有的项目 select @projectCount = count ...

  10. 初识PCA数据降维

    PCA要做的事降噪和去冗余,其本质就是对角化协方差矩阵. 一.预备知识 1.1 协方差分析 对于一般的分布,直接代入E(X)之类的就可以计算出来了,但真给你一个具体数值的分布,要计算协方差矩阵,根据这 ...