Quartz是一个开源的任务调度系统,它能用来调度很多任务的执行。
运行环境•Quartz 能嵌入在其他应用程序里运行。 •Quartz 能在一个应用服务器里被实例化(或servlet容器), 并且参与XA事务
•Quartz能独立运行(通过JVM),或者通过RMI •Quartz能被集群实例化
任务调度当一个指定给任务的触发器发生时,任务就被调度执行. 触发器能被创建为:
•一天的某个时间(精确到毫秒级) •一周的某些天 •一个月的某些天 •一年的某些天 •不在一个Calendar列出的某些天 (例如工作节假日) •在一个指定的次数重复
•重复到一个指定的时间/日期
•无限重复 •在一个间隔内重复
能够给任务指定名称和组名.触发器也能够指定名称和组名,这样可以很好的在调度器里组织起来.一个加入到调度器里的任务可以被多个触发器注册。在J2EE环境里,任务能作为一个分布式(XA)事务的一部分来执行。

任务执行•任务能够是任何实现Job接口的Java类。 •任务类能够被Quartz实例化,或者被你的应用框架。 •当一个触发器触发时,调度器会通知实例化了JobListener 和TriggerListener 接口的0个或者多个Java对象(监听器可以是简单的Java对象, EJBs, 或JMS发布者等). 在任务执行后,这些监听器也会被通知。 •当任务完成时,他们会返回一个JobCompletionCode ,这个代码告诉调度器任务执行成功或者失败.这个代码也会指示调度器做一些动作-例如立即再次执行任务。 任务持久化•Quartz的设计包含JobStore接口,这个接口能被实现来为任务的存储提供不同的机制。 •应用JDBCJobStore, 所有被配置成“稳定”的任务和触发器能通过JDBC存储在关系数据库里。 •应用RAMJobStore, 所有任务和触发器能被存储在RAM里因此不必在程序重起之间保存-一个好处就是不必使用数据库。 事务•使用JobStoreCMT(JDBCJobStore的子类),Quartz 能参与JTA事务。 •Quartz 能管理JTA事务(开始和提交)在执行任务之间,这样,任务做的事就可以发生在JTA事务里。集群•Fail-over. •Load balancing. 监听器和插件•通过实现一个或多个监听接口,应用程序能捕捉调度事件来监控或控制任务/触发器的行为。 •插件机制可以给Quartz增加功能,例如保持任务执行的历史记录,或从一个定义好的文件里加载任务和触发器。 •Quartz 装配了很多插件和监听器。
1.使用Quartz在我们用调度器之前,调度器需要实例化。我们用SchedulerFactory 来实例它。一旦调度器被实例,我们就可以启动它,置它为stand-by模式,最后关闭它。注意:一旦一个调度器被关闭了,如果我们不重新实例化它,它就不可能被再次启动。直到调度器启动了或者当调度器处于暂停状态,触发器才能够触发。下面有个简单的例子:
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
JobDetail jobDetail = new JobDetail("myJob",
null,
DumbJob.class);
Trigger trigger = TriggerUtils.makeHourlyTrigger(); // 每个小时触发
trigger.setStartTime(TriggerUtils.getEvenHourDate(new Date())); // 在下个小时开始
trigger.setName("myTrigger");
sched.scheduleJob(jobDetail, trigger);
就象你看到的,使用Quartz是很简单的。在下一节我们介绍Jobs和Triggers。
2.Jobs 和 Triggers就象以前提到的,一个实现了Job接口的Java类就能够被调度器执行。接口如下:
package org.quartz;
public interface Job {
public void execute(JobExecutionContext context) throws JobExecutionException;
}
很简的,当Job的trigger触发时,Job的execute(..)方法就会被调度器调用。被传递到这个方法里来的JobExecutionContext对象提供了带有job运行时的信息:执行它的调度器句柄、触发它的触发器句柄、job的JobDetail对象和一些其他的项。
JobDetail对象是Job在被加到调度器里时所创建的,它包含有很多的Job属性设置,和JobDataMap一样,可以用来存储job实例时的一些状态信息。
Trigger对象是用来触发执行Job的。当调度一个job时,我们实例一个触发器然后调整它的属性来满足job执行的条件。触发器也有一个和它相关的JobDataMap,它是用来给被触发器触发的job传参数的。Quartz有一些不同的触发器类型,不过,用得最多的是SimpleTrigger和CronTrigger。
如果我们需要在给定时刻执行一次job或者在给定时刻触发job随后间断一定时间不停的执行的话,SimpleTrigger是个简单的解决办法;如果我们想基于类似日历调度的触发job的话,比如说,在每个星期五的中午或者在每个月第10天的10:15触发job时,CronTrigger是很有用的。
为什么用jobs和triggers呢?很多任务调度器并没有任务和触发器的概念,一些任务调度器简单定义一个“job”为在一个执行时间伴随一些小任务标示,其他的更像Quartz里job和trigger对象的联合体。在开发Quartz时,开发者们决定,在调度时间表和在这上面运行的工作应该分开。这是很有用的。
例如,job能够独立于触发器被创建和储存在任务调度器里,并且,很多的触发器能够与同一个job关联起来。这个松耦合的另一个好处就是在与jobs关联的触发器终止后,我们能够再次配置保留在调度器里的jobs,这样的话,我们能够再次调度这些jobs而不需要重新定义他们。我们也可以在不重新定义一个关联到job的触发器的情况下,修改或替代它。
当Jobs和triggers被注册到Quartz的调度器里时,他们就有了唯一标示符。他们也可以被放到“groups”里,Groups是用来组织分类jobs和triggers的,以便今后的维护。在一个组里的job和trigger的名字必须是唯一的,换句话说,一个job和trigger的全名为他们的名字加上组名。如果把组名置为”null”,系统会自动给它置为Scheduler.DEFAULT_GROUP
现在,我们大概有了一些jobs和triggers的理解,随后2节我们将根多的了解它们。
3.更多关于Jobs & JobDetailsJobs很容易实现,这儿有更多我们需要理解的东西:jobs的本质,job接口的execute(..)方法,关于JobDetails。
当我们实现的一个class是真正的”job”时,Quartz需要知道各种job有的属性,这是通过JobDetail类做到的。在没用JobDetail之前,JobDetail的功能的实现是通过在每个job的实现类上加上所有的现在JobDetail的get方法来实现的。这就在每个job类上强加了一些实现一样功能的代码,就显得每个job类很笨重,于是,Quartz开发者们就创造了JobDetail类。
现在,我们来讨论一下在Quartz里job的本质和job实例的生命周期。首先我们来看看第一节的代码片段:  
JobDetail jobDetail = new JobDetail("myJob",      // job 名称
sched.DEFAULT_GROUP, // job组名(可以写'null'来用default group)
DumbJob.class);         //要执行的java
Trigger trigger = TriggerUtils.makeDailyTrigger(8, 30);
trigger.setStartTime(new Date());
trigger.setName("myTrigger");
sched.scheduleJob(jobDetail, trigger);
现在我们定义“DumbJob”类:
public class DumbJob implements Job {
public DumbJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException
{
System.err.println("DumbJob is executing.");
}
}
可以看到我们给调度器一个JobDetail实例,并且,它通过job的类代码引用这个job来执行。每次调度器执行job时,它会在调用job的execute(..)方法之前创建一个他的实例。这就带来了两个事实:一、job必须有一个不带参数的构造器,二、在job类里定义数据成员并没有意义,因为在每次job执行的时候他们的值会被覆盖掉。
你可能现在想要问“我怎样给一个job实例提供属性/配置?”和“在几次执行间我怎样能跟踪job的状态?”这些问题的答案是一样的:用JobDataMap- JobDetail对象的一部分。

JobDataMapJobDataMap能够支持任何序列化的对象,当job执行时,这些对象能够在job实例中可用。JobDataMap实现了Java Map接口,它有一些附加的方法,这些方法用来储存和跟踪简单类型的数据。
如下代码可以很快地给job增加JobDataMap:
jobDetail.getJobDataMap().put("jobSays", "Hello World!");
jobDetail.getJobDataMap().put("myFloatValue", 3.141f);
jobDetail.getJobDataMap().put("myStateData", new ArrayList());
在job执行时,我们可以在job里通过如下代码得到JobDataMap:
public class DumbJob implements Job {
public DumbJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException
{
String instName = context.getJobDetail().getName();
String instGroup = context.getJobDetail().getGroup();
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String jobSays = dataMap.getString("jobSays");
float myFloatValue = dataMap.getFloat("myFloatValue");
ArrayList state = (ArrayList)dataMap.get("myStateData");
state.add(new Date());
System.err.println("Instance " + instName + " of DumbJob says: " + jobSays);
}
}
如果用一个持久JobStore(在指南JobStore章节讨论),我们就应该注意在JobDataMap里放些什么,因为在它里面的对象将会被序列化,并且这些对象会因此产生一些class-versioning问题。明显的,标准Java类型应该是很安全的,但是,任何时候某人改变了一个你已经序列化的实例的类的定义时,我们就要注意不能够破坏兼容性了。在这个方面的进一步信息可以在Java Developer Connection Tech Tip: Serialization In The Real World里找到。我们能把JDBC-JobStore和JobDataMap放到一个模式里,在那里,只有简单类型和String型能被储存在Map里,从而消去任何以后的序列化问题。

Stateful vs. Non-Stateful Jobs
触发器也有与它们关联的JobDataMaps。假设我们有一个储存在调度器里被多个触发器关联的job,然而,对于每个独立的触发器,我想提供给job不同的数据输入,在这个时候,JobDataMaps就很有用了。
在job执行期间,JobDataMaps能够在JobExecutionContext里获得。JobDataMap融合在Trigger和JobDetail类里,JobDataMap里面的值能够利用key来更新。
以下例子显示,在job执行期间从JobExecutionContext里的JobDataMap得到数据:

public class DumbJob implements Job {
public DumbJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException
{
String instName = context.getJobDetail().getName();
String instGroup = context.getJobDetail().getGroup();
JobDataMap dataMap = context.getJobDataMap();  // 注意:不同于以前的例子
String jobSays = dataMap.getString("jobSays");
float myFloatValue = dataMap.getFloat("myFloatValue");
ArrayList state = (ArrayList)dataMap.get("myStateData");
state.add(new Date());
System.err.println("Instance " + instName + " of DumbJob says: " + jobSays);
}
}

StatefulJob现在,关于job状态数据的一些附加要点:一个job实例能定义为"有状态的"或者"无状态的"。无状态的jobs仅当它们在被加入到调度器里时才存储JobDataMap。这就意味着,在jobs执行期间对JobDataMap里数据的任何改变都会丢失,下次执行时job将看不到这些数据。你可能会猜到,一个有状态的job就是它的反面例子-它的JobDataMap是在每次执行完job后再次储存的。一个缺点就是有状态的job不能够并发执行。换句话说,如果job是有状态的,一个触发器尝试触发这个已经执行了的job时,这个触发器就会等待直到这次执行结束。
用实现StatefulJob 接口来标记一个job是有状态的。
Job 'Instances'我们能够创建一个单独的job类,并且通过创建多个JobDetails实例在调度器里储存很多它的“实例定义”,每个都有它自己的属性集和JobDataMap ,把它们都加入到调度器里。
当一个触发器触发时,与它关联的job就是通过配置在调度器上的JobFactory 来实例化的。默认的JobFactory 简单的调用在job类上的newInstance()方法,你可能想要创建自己的JobFactory实现来完成一些自己想要的事情,如:拥有应用程序的IoC或者DI容器进程/初始化job实例。

job的其他属性这儿有一个其他属性的总结,这些属性是通过JobDetail对象为一个job实例定义的。
•持久性– 如果一个job是非持久的,一旦没有任何可用的触发器与它关联时,他就会自动得从调度器里被删除。 •不稳定性-如果一个job是不稳定的,他就不会在重起Quartz调度器之间持久化。
•请求恢复– 如果一个job“请求恢复”,在调度器“硬关闭”(如:该进程崩溃,机器被关掉)时这个job还在执行,过后,当调度器再次启动时,他就会再次执行。在这种情况下,JobExecutionContext.isRecovering() 方法将会返回true. •Job监听器 –一个job能够有0个或者多个与它关联的监听器。当job执行时,监听器就会被通知。在监听器的更多讨论请看TriggerListeners & JobListeners
JobExecutionException最后,我们来看看Job.execute(..)方法的一些细节。你能够从execute方法里抛出的仅有的异常类型就是JobExecutionException。因为这样,我们应该使用try-catch块包围整个execute方法内容。我们还应该花一些时间看看JobExecutionException文档。当job执行发生异常时,通过设置JobExecutionException,可以让此job再次进入调度器或者今后不再运行。
4.更多关于Triggers象jobs一样,triggers也相对来说很容易。但是,我们还是要理解它的一些特性。Quartz里也有很多类型的trigger提供给我们使用。
CalendarsQuartz Calendar 对象(不是java.util.Calendar对象)能够在trigger储存在调度器时和trigger关联起来。Calendars主要用来在trigger配置时排除一些时间。例如,你能够创建一个在每个工作日早上9:30触发的trigger,然后为这个trigger增加一个排除所有商业的节假日的Calendar。
Calendars能够是任何序列化的对象,只要这些对象实现了Calendar接口:
package org.quartz;
public interface Calendar {
public boolean isTimeIncluded(long timeStamp);
public long getNextIncludedTime(long timeStamp);
}
注意到这些方法的参数类型是long。这意味着calendars能够排除毫秒级的时间段。大部分地,我们感兴趣的是一整天的,所以在Quartz里,有个实现类提供了方便:org.quartz.impl.HolidayCalendar
Calendars必须被实例化并且通过addCalendar(..)方法注册到调度器里。如果你用HolidayCalendar,在实例它之后,你应该用它的addExcludedDate(Date date)方法以便组装上你想排除的那几天。一个calendar实例能够被多个triggers使用:

HolidayCalendar cal = new HolidayCalendar();
cal.addExcludedDate( someDate );
sched.addCalendar("myHolidays", cal, false);
Trigger trigger = TriggerUtils.makeHourlyTrigger(); // 每小时触发
trigger.setStartTime(TriggerUtils.getEvenHourDate(new Date()));  //下一个小时开始  trigger.setName("myTrigger1");
trigger.setCalendarName("myHolidays");
// .. schedule job with trigger
Trigger trigger2 = TriggerUtils.makeDailyTrigger(8, 0); // 每天早上8点触发
trigger2.setStartTime(new Date()); //立即开始
trigger2.setName("myTrigger2");
trigger2.setCalendarName("myHolidays");
// .. schedule job with trigger2

不触发(misfire)指令触发器的另外一个重要的属性是“不触发指令”。如果一个持久的触发器由于调度器被关闭了而没有找到它的触发时间,那么一个不触发将会发生。不同的触发器类型有不同的不触发指令。默认的,他们都用“smart policy”指令-这是一个基于触发器类型和配置的动态行为。当调度器启动时,他将会搜寻所有没触发的持久化的triggers,然后基于他们各个配置的不触发指令来更新他们。当你用Quartz,你应该熟悉各个不触发指令,我们在以下章节有一些介绍。给一个trigger实例配置不触发指令,要用此实例的setMisfireInstruction(..)方法。

TriggerUtils - Triggers Made EasyTriggerUtils类(在org.quartz包里)包含了很多方便的工具。能够帮你创建triggers和datas。用这个类能够很容易制造一些trigges,这些triggers能够在每分钟,每小时,每周,每个月等等触发。用它也能产生一些接近某个秒、分钟、小时的天-这在设置trigger的启动时间很有帮助。
TriggerListeners最后,triggers有一些注册了的监听器,象job一样。实现了TriggerListener接口的对象将接受一个trigger被触发的通知。

5. SimpleTrigger详细介绍一下它的构造器:
public SimpleTrigger(String name, //trigger名称
String group, //trigger的组名
Date startTime, //开始时间
Date endTime, //结束时间
int repeatCount, //重复次数
long repeatInterval)//重复间隔
举几个常用例子:
从现在开始10秒后执行一次:
long startTime = System.currentTimeMillis() + 10000L;
SimpleTrigger trigger = new SimpleTrigger("myTrigger",
null,
new Date(startTime),
null,
0,
0L);
立即执行,60秒间隔无限制重复:
SimpleTrigger trigger = new SimpleTrigger("myTrigger",
null,
new Date(),
null,
SimpleTrigger.REPEAT_INDEFINITELY,
60L * 1000L);
从现在开始立即执行,每10秒重复,直到40秒后:
long endTime = System.currentTimeMillis() + 40000L;
SimpleTrigger trigger = new SimpleTrigger("myTrigger",
"myGroup",
new Date(),
new Date(endTime),
SimpleTrigger.REPEAT_INDEFINITELY,
10L * 1000L);
在2002年3月17号10:30am触发,重复5次(一共6次),30秒间隔:
java.util.Calendar cal = new java.util.GregorianCalendar(2002, cal.MARCH, 17);
cal.set(cal.HOUR, 10);
cal.set(cal.MINUTE, 30);
cal.set(cal.SECOND, 0);
cal.set(cal.MILLISECOND, 0);
Data startTime = cal.getTime();
SimpleTrigger trigger = new SimpleTrigger("myTrigger",
null,
startTime,
null,
5,
30L * 1000L);
SimpleTrigger 不触发指令MISFIRE_INSTRUCTION_FIRE_NOW

MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT

MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT

MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT

MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT

6.CronTrigger构造器CronTrigger(String name, //触发器名称
String group, //触发器的组名
String jobName, //job名称
String jobGroup, //job的组名
Date startTime, //开始时间
Date endTime, //结束时间
String cronExpression, //克隆表达式
TimeZone timeZone)//时区
还有一些其它参数少一些的构造器,参考JavaDoc。通常我们如下简单地使用CronTrigger;
Trigger trigger = new CronTrigger("trigger1", "group1");//设置触发器名称和组名
trigger.setCronExpression("0 0 15 * * ?");//设置克隆表达式

克隆表达式一个克隆表达式是一个由空白间隔6个或者7个字段的字符串。

格式:

字段名
必须有?
值范围
允许的特殊字符

Seconds
YES
0-59
, - * /

Minutes
YES
0-59
, - * /

Hours
YES
0-23
, - * /

Day of month
YES
1-31
, - * ? / L W C

Month
YES
1-12 or JAN-DEC
, - * /

Day of week
YES
1-7 or SUN-SAT
, - * ? / L C #

Year
NO
empty, 1970-2099
, - * /


例子:

* * * * ? *
0 0/5 14,18,3-39,52 ? JAN,MAR,SEP MON-FRI 2002-2010
特殊字符•* 表示所有值 ;
•? 表示未说明的值,即不关心它为何值; •- 表示一个指定的范围; •, 表示附加一个可能值; •/ 符号前表示开始时间,符号后表示每次递增的值; •L ("last") "L" 用在day-of-month字段意思是 "这个月最后一天";用在 day-of-week字段, 它简单意思是 "7" or "SAT"。 如果在day-of-week字段里和数字联合使用,它的意思就是 "这个月的最后一个星期几" – 例如: "6L" means "这个月的最后一个星期五". 当我们用“L”时,不指明一个列表值或者范围是很重要的,不然的话,我们会得到一些意想不到的结果。•W ("weekday") –只能用在day-of-month字段。用来描叙最接近指定天的工作日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个月第15天的工作日”,即如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第16天即周一触发;如果这个月第15天是周二,那么就在触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在day-of-month指明一天,不能是一个范围或列表。
也可以用“LW”来指定这个月的最后一个工作日。
•# -只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用"6#3"指这个月第3个周五(6指周五,3指第3个)。如果指定的日期不存在,触发器就不会触发。 •C ("calendar") – 指和calendar联系后计算过的值。例:在day-of-month 字段用“5C”指在这个月第5天或之后包括calendar的第一天;在day-of-week字段用“1C”指在这周日或之后包括calendar的第一天。 在MONTH和Day of week字段里对字母大小写不敏感。
一些例子表达式
意思(触发时刻)

0 0 12 * * ?
每天中午12点

0 15 10 * * ? 2005
在2005年的每天10:25

0 10,44 14 ? 3 WED
在3月里每个周三的14:10和14:44

0 15 10 ? * 6L 2002-2005
从2002年到2005年里,每个月的最后一个星期五的10:15

0 0 12 1/5 * ?
从当月的第一天开始,然后在每个月每隔5天的12:00

0 15 10 ? * 6#3
每个月第3个周五的10:15


注意在day-of-week和day-of-month字段里使用“?”和“*”的效果。

注意•对“C”的支持并不很完全。 •对在day-of-week字段 和在day-of-month字段同时使用也不是很完全(目前你必须在这两个字段中的一个用“?”指定)。 •当设置在午夜和凌晨1点之间触发时要仔细。
不触发指令:
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW

MISFIRE_INSTRUCTION_DO_NOTHING

7.TriggerListeners 和JobListeners与Trigger相关的事件有:触发器触发,触发器的不触发(参考先前章节),触发器完成。

public interface TriggerListener {
public String getName();
public void triggerFired(Trigger trigger, JobExecutionContext context);
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context);
public void triggerMisfired(Trigger trigger);
public void triggerComplete(Trigger trigger, JobExecutionContext context,
int triggerInstructionCode);
}
与job相关的事件有:job准备执行,job执行完毕。
public interface JobListener {
public String getName();
public void jobToBeExecuted(JobExecutionContext context);
public void jobExecutionVetoed(JobExecutionContext context);
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException);
}
使用Listeners创建一个监听器,就是创建一个实现了org.quartz.TriggerListener 和 org.quartz.JobListener接口的对象。在运行的期间用调度器注册监听器,必须要给它提供一个名字。监听器能够注册成为全局的或者不是全局的,全局监听器接受所有的事件,而非全局的则仅接受指定给triggers/jobs了的事件。

监听器是在运行期间被调度器注册的,他们没有伴随jobs和triggers储存在JobStore里。Jobs和triggers仅储存和它们相关的监听器的名字。因此,每次程序运行时,监听器需要被调度器再次注册。
scheduler.addGlobalJobListener(myJobListener);
scheduler.addJobListener(myJobListener);

监听器在Quartz并不是经常使用的。

8.SchedulerListeners和调度器相关的事件有:job/trigger的加入和移出,一些调度器里的错误,调度器关闭等等。

public interface SchedulerListener {
public void jobScheduled(Trigger trigger);
public void jobUnscheduled(String triggerName, String triggerGroup);
public void triggerFinalized(Trigger trigger);
public void triggersPaused(String triggerName, String triggerGroup);
public void triggersResumed(String triggerName, String triggerGroup);
public void jobsPaused(String jobName, String jobGroup);
public void jobsResumed(String jobName, String jobGroup);
public void schedulerError(String msg, SchedulerException cause);
public void schedulerShutdown();
}
创建和注册SchedulerListeners和其他监听器一样,全局和非全局的没有区别。

9.JobStoresJobStore负责保存所有配置到调度器里的工作数据:jobs,triggers,calendars等等。在用SchedulerFactory得到一个调度器的实例时,我们可以给SchedulerFactory提供一个属性文件或者一个属性对象来声明使用哪个JobStore。
注意,不要在代码里使用JobStore的实例,这些Quartz都做好了。我们要做的就仅仅告诉Quartz(通过配置)用哪个JobStore,然后就调用Scheduler接口函数了。

RAMJobStore利用内存来持久化调度程序信息。这种作业存储类型最容易配置、构造和运行,但是当应用程序停止运行时,所有调度信息将被丢失。

在属性文件里指定:

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
JDBCJobStore支持的数据库有:Oracle, MySQL, MS SQLServer2000, HSQLDB, PostreSQL and DB2。使用JDBCJobStore,首先要在数据库里建一些Quartz要使用的表。我们可以使用Quartz发布包里的建表脚本,在docs/dbTables目录下。如果没有你所要的数据库类型的脚本,可以在已有的脚本作一些修改。所有这些标都是以“QRTZ_”作为前缀的,这个前缀是可以在属性文件里更改的。在为多个调度器实例创建多个系列的表时,用不同的前缀是很有用的。

一旦我们创建了这些表,在配置和触发JDBCJobStore之前就要做更多的事情了。我们需要决定应用需要哪种类型的事务处理。如果我们不需要给其他的事务处理一些调度命令(增加删除trigger),我们就可以让Quartz利用JobStoreTX处理这个事务(这用的很多)。

如果我们需要Quartz和其他的事务处理(在J2EE应用服务器里)一起工作,我们就应该用JobStoreCMT-这会使Quartz让应用服务器容器管理事务。
最后一点是从哪个JDBCJobStore启动数据库能够得到该数据库的连接。在属性文件里是用一个不同的方法来定义数据源的。一种是Quartz自己创建和管理数据源-提供所有的数据库连接信息;另外一种是利用应用服务器管理的数据源,其中Quartz运行在这个应用服务器里-给JDBCJobStore提供数据库的JNDI名称。

用JDBCJobStore(假设我们是用的StdSchedulerFactory),我们首先要设置org.quartz.jobStore.class属性为org.quartz.impl.jdbcjobstore.JobStoreTX或者org.quartz.impl.jdbcjobstore.JobStoreCMT,这取决于我们的选择。

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
下一步,我们需要选择一个驱动代理。StdJDBCDelegate是一个用“vanilla”JDBC代码实现的代理。如果没有其他为你数据库指定的代理,就使用这个。Quartz开发者们解决的问题都是根据这个代理的来实现的。其他的代理在org.quartz.impl.jdbcjobstore包或者子包里。包括DB2v6Delegate(DB2 version 6 或早期版本使用的),HSQLDBDelegate(HSQLDB使用),MSSQLDelegate(microsoft SQLServer 2000使用),PostgreSQLDelegate(PostgreSQL7.x使用),WeblogicDelegate(Weblogic的JDBC驱动器使用),OracleDelegate(Oracle 8i and 9i使用)。

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
在下一步,我们要配置表的前缀:
org.quartz.jobStore.tablePrefix = QRTZ_
最后,我们需要设置用哪个数据源,数据源的名称必须在Quartz属性里定义好。例如,我们可以给Quartz指定使用“myDS”(在配置属性里的其他地方定义好了)作为数据源的名字。
org.quartz.jobStore.dataSource = myDS
如果调度器很繁忙(例如,执行job的个数和线程池的大小一样),那么我们应该设置数据源的连接个数在线程池大小+1之上。
org.quartz.jobStore.useProperties这个属性能够设置为“true”(默认为false),用来指示JDBCJobStore:在JobDataMaps里的所有值都应该是String,这样在能作为name-value方式储存,而不是在BLOB列里以序列化的格式储存复杂的对象。从长远看,这样做会很安全,因为你可以避免将非String的类序列化到BLOB里的类版本问题。
10.配置,资源使用和调度器工厂Quartz是以标准组件的方式组织的,所以,使它运行起来,一些组件需要被联合起来。
在Quartz能够工作之前,需要配置的主要组件有:
•线程池 •作业储存 •数据源(需要的话)
•调度器自己
在运行jobs时,线程池为Quartz提供了一系列的线程。在线程池里的线程越多,能够并行执行的jobs就越多。但是,太多的线程会使系统瘫痪。大部分的Quartz用户发现,5个线程就足够了-因为他们在指定时间里只有少于100的jobs,这些jobs并不都是在同一时刻执行,jobs完成得也很快的。其他的用户发现他们需要10、15、50或者100个线程-因为他们在不同的调度器里用了上万个触发器,在给定的时间里,平均在10到100个jobs试着执行。为调度器找到合适的线程数量完全依赖于你用调度起来做什么。不在乎线程数量,而要确保你有足够的线程来使jobs执行。如果一个触发器的触发时间到来了,可是没有一个能够用的线程,Quartz将会等到可用线程的来临,然后job将会在几毫秒后执行。这可能会引起不触发-如果不在属性文件里给调度器配置“misfirethreshold”的话。
线程池接口是在org.quartz.spi包里定义的,你能够创建一个线程池以自己的方法。Quartz装配了一个简单(但是很好的)的线程池,是org.quartz.simpl.SimpleThreadPool。这个线程池简单的维护一些在池里固定的线程-不会增加也不会减少。但是它能够做很多事而且经过测试了的,几乎每个Quartz用户用这个线程池。
JobStores 和 DataSrouces在前面讨论过了,这里值得一提的是,所有JobStores都实现了org.quartz.spi.JobStore接口,如果在打包里的任何一个JobStore不能够满足你的需求的话,你可以自己做一个。
最后,你需要创建你的Scheduler实例。Scheduler需要提供他的名称,说明RMI的设置,处理JobStore和ThreadPool的实例。RMI设置包括调度器是否作为一个RMI服务器而创建。StdSchedulerFactory也能够产生调度器的实例,这些实例实际上是创建在远程进程中的调度器代理(RMI桩)。

StdSchedulerFactoryStdSchedulerFactory实现了org.quartz.SchedulerFactory接口。它用了一系列的属性(java.util.Properties)来创建和初始化一个Quartz的调度器。这些属性通常保存和加载在一个文件里,但是也可以通过你的程序创建直接交给工厂处理。在工厂上调用getScheduler()就可以产生调度器,初始化它(还有线程池,JobStore和数据源),然后返回一个句柄到这个公共的接口。
// 默认调度器是quartz.propeties文件定义的,这个文件可以在当前目录下找到,也可以在//classpath里找到,如果都找不到了,就用quartz.jar里的quartz.propeties文件。
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
scheduler.start();
用指定的属性对象初始化:
SchedulerFactory sf = new StdSchedulerFactory();
sf.initialize(schedulerProperties);// schedulerProperties是属性对象
Scheduler scheduler = sf.getScheduler();
scheduler.start();
用指定的属性文件初始化:
SchedulerFactory sf = new StdSchedulerFactory();
sf.initialize(fileName);//属性文件全名
Scheduler scheduler = sf.getScheduler();
scheduler.start();
DirectSchedulerFactoryDirectSchedulerFactory是另外的一个SchedulerFactory实现。在更多的编程方法里创建调度器时,他很有用。他的用法不被赞成,原因有:1.它需要用户更清楚的知道他们在做什么。2.它不允许配置,就是说,你必须要在代码里配置所有的调度器属性。

LoggingQuartz给它所有需要的日志是使用org.apache.commons.logging框架的。Quartz没有产生很多的日志信息。仅有一些在初始化时关于一些jobs正在执行的问题的信息。为了调整日志设置,我们需要了解Jakarta Commons Logging框架,超过了本文档讨论的范围。


11.高级(企业)特性集群目前集群仅以JDBC-Jobstore (JobStoreTX or JobStoreCMT)工作。这些特性包含load-balancing和任务fail-over(如果JobDetail的"request recovery"标志设为true的话)。
通过设置org.quartz.jobStore.isClustered属性为“true”来使用集群。在集群里的每个调度器实例应该用一样的quartz.properties文件。集群会有如下异常:线程池大小不同,属性org.quartz.scheduler.instanceName值不同。其实在集群的每个节点都有一个唯一的实例ID,要达到这样也很简单,也不需要不同的属性文件,只要将属性org.quartz.scheduler.instanceId的值设置为“AUTO”。
不要在一个分离开的机器上运行集群,除非他们的时钟是用时钟同步服务同步过的。如果不熟悉怎样同步,参考:http://www.boulder.nist.gov/timefreq/service/its.htm
其他调度器实例在用数据表时,不要触发一个也用到这些数据表的不是集群的调度器实例。你会得到一些没用的数据。


JTA 事务在第9节解释过JobStores,JobStoreCMT允许Quartz调度一些具有很大JTA事务的操作。

通过设置“org.quartz.scheduler.wrapJobExecutionInUserTransaction”属性为true,Jobs也能够在一个JTA事务里执行。有了这个设置,一个JTA事务会在job的execute()方法调用前开始(begin),然后在调用execute()方法结束后提交(commit)。

除了在JTA事务里Quartz自动地和job的执行挂钩之外,当使用JobStoreCMT时也可以调用你在调度器接口里的实现的方法,确保你在调用一个调度器上的方法之前开始了事务。你也可以直接自己做,使用UserTransaction,或者把用了调度器的代码放在一个使用容器的SessionBean里来管理事务。

12. Quartz 的其他特性Plug-InsQuartz 提供了一个接口(org.quartz.spi.SchedulerPlugin) 来实现plugging-in 的功能。
装配给Quartz的Plugins能提供不同的有用的功能。在org.quartz.plugins包里有详细说明。他们提供的功能例如:调度器启动时自动调度jobs,记录job和triggers事件的历史,当JVM退出时确保调度器关闭。
可以通过配置属性文件来使用自己实现或Quartz自带的插件。

JobFactory当一个trigger触发时,通过一个配置到调度器上的JobFactory,与trigger相关的job就被实例化了。默认的JobFactory会在job类上调用newInstance(),你可能想要创建自己的JobFactory实现来完成一些其他的事情,如:拥有应用程序的IoC或者DI容器进程/初始化job实例。
与Scheduler.setJobFactory(fact)方法联合起来察看org.quartz.spi.JobFactory接口,

Jobs工具
Quartz也提供一些有用的job,你能够用这些job来发邮件或者调用EJB。我们能在org.quartz.jobs包里找到它们。
13.配置文件里配置项总结设置主要调度器属性名
必须
类型
缺省值

org.quartz.scheduler.instanceName
no
string
'QuartzScheduler'

org.quartz.scheduler.instanceId
no
string
'NON_CLUSTERED'

org.quartz.scheduler.threadName
no
string
instanceName + '_QuartzSchedulerThread'

org.quartz.scheduler.idleWaitTime
no
long
30000

org.quartz.scheduler.dbFailureRetryInterval
no
long
15000

org.quartz.scheduler.classLoadHelper.class
no
string (class name)
org.quartz.simpl.CascadingClassLoadHelper

org.quartz.context.key.SOME_KEY
no
string
none

org.quartz.scheduler.userTransactionURL
no
string (url)
'java:comp/UserTransaction'

org.quartz.scheduler.wrapJobExecutionInUserTransaction
no
booelan
false

org.quartz.scheduler.jobFactory.class
no
string (class name)
org.quartz.simpl.SimpleJobFactory


org.quartz.scheduler.instanceName
任意的String,对于调度器自己并没有意义。但是当多个调度器实例用在一个程序里时,他就可以用来为客户端代码区别每个调度器。如果你用集群这个特性,你必须为在集群里的每个实例用一样的名字,实现逻辑上的一样的调度器。

org.quartz.scheduler.instanceId
任意的String,如果在一个集群里多个实例是一个逻辑上一样的调度器时,每个实例的这项属性必须唯一。你可以设置这项为“AUTO”从而自动收集ID。
org.quartz.scheduler.idleWaitTime
当调度器空闲时,在再次查询可用triggers之前,调度器将要等等待的毫秒数。正常情况下,我们不调整这个参数,除非我们用XA事务,或者在立即触发trigger时结果延误了。
org.quartz.scheduler.classLoadHelper.class
不需要更改。
org.quartz.context.key.SOME_KEY
设置org.quartz.context.key.MyKey = MyValue等价于scheduler.getContext().put("MyKey", "MyValue")
org.quartz.scheduler.userTransactionURL
是一个JNDI URL,Quartz用它来定位应用服务器的UserTransaction管理器。Websphere用户可能需要设置它为“jta/usertransaction”。在Quartz配置用到JobStoreCMT时并且属性org.quartz.scheduler.wrapJobExecutionInUserTransaction设置为true时才有用。
org.quartz.scheduler.wrapJobExecutionInUserTransaction
设置这项为true使我们在调用job的execute()之前能够开始一个UserTransaction。在job的execute()完成之后,事务将会提交,并且,JobDataMap也更新了(是有状态的job)。

设置线程池属性名
必须
类型
缺省值

org.quartz.threadPool.class
yes
string (clas name)
null

org.quartz.threadPool.threadCount
yes
int
-1

org.quartz.threadPool.threadPriority
no
int
Thread.NORM_PRIORITY (5)

org.quartz.threadPool.makeThreadsDaemons
no
boolean
false

org.quartz.threadPool.threadsInheritGroupOfInitializingThread
no
boolean
true

org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread
no
boolean
false


org.quartz.threadPool.class
通常使用org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadPriority
在 Thread.MIN_PRIORITY (1) 和Thread.MAX_PRIORITY (10)之间
org.quartz.threadPool.makeThreadsDaemons、org.quartz.threadPool.threadsInheritGroupOfInitializingThread 和org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread 三个属性是指定的SimpleThreadPool的属性。
如果用自己实现的线程池,可如下配置:

org.quartz.threadPool.class = com.mycompany.goo.FooThreadPool
org.quartz.threadPool.somePropOfFooThreadPool = someValue
设置全局监听器全局监听器要有一个无参数的构造器,它的属性是通过反射设置的,仅支持简单数据和String。

Trigger监听器:

org.quartz.triggerListener.NAME.class = com.foo.MyListenerClass
org.quartz.triggerListener.NAME.propName = propValue
org.quartz.triggerListener.NAME.prop2Name = prop2Value

job监听器:

org.quartz.jobListener.NAME.class = com.foo.MyListenerClass
org.quartz.jobListener.NAME.propName = propValue
org.quartz.jobListener.NAME.prop2Name = prop2Value

设置Plugins配置自己的插件(和全局监听器差不多):

org.quartz.plugin.NAME.class = com.foo.MyPluginClass
org.quartz.plugin.NAME.propName = propValue
org.quartz.plugin.NAME.prop2Name = prop2Value
也可以配置Quartz实现的插件:
1.trigger历史日志记录插件(属性配置中的{数字}参考JavaDoc):
org.quartz.plugin.triggHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.quartz.plugin.triggHistory.triggerFiredMessage=
Trigger {1}.{0} fired job {6}.{5} at:{4, date, HH:mm:ss MM/dd/yyyy}
org.quartz.plugin.triggHistory.triggerCompleteMessage =
Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss MM/dd/yyyy}
2.从XML文件中初始化job的插件(属性配置中的文件名是加载jobs用到的xml文件,这个文件必须在classPath里):
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileName =data/my_job_data.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
在上例中,JobInitializationPlugin只支持一个xml文件的初始化,Quartz还提供多个xml文件的初始化,用JobInitializationPluginMultiple,文件名用“,”隔开。
含有多个Jobs的一个xml文件的一个例子:
<?xml version='1.0' encoding='utf-8'?>
<quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
version="1.5">

<calendar class-name="org.quartz.impl.calendar.HolidayCalendar" replace="true">
<name>holidayCalendar</name>
<description>HolidayCalendar</description>
<base-calendar class-name="org.quartz.impl.calendar.WeeklyCalendar">
<name>weeklyCalendar</name>
<description>WeeklyCalendar</description>
<base-calendar class-name="org.quartz.impl.calendar.AnnualCalendar">
<name>annualCalendar</name>
<description>AnnualCalendar</description>
</base-calendar>
</base-calendar>
</calendar>

<job>
<job-detail>
<name>testJob1</name>
<group>testJobs</group>
<description>Test Job Number 1</description>
<job-class>personal.ruanyang.quartz.plugin.SimpleJob</job-class>
<volatility>false</volatility>
<durability>false</durability>
<recover>false</recover>      
<job-data-map allows-transient-data="true">
<entry>
<key>test1</key>
<value>test1</value>
</entry>
<entry>
<key>test2</key>
<value>test2</value>
</entry>
</job-data-map>      
</job-detail>
<trigger>
<cron>
<name>testTrigger1</name>
<group>testJobs</group>
<description>Test Trigger Number 1</description>
<job-name>testJob1</job-name>
<job-group>testJobs</job-group>

<!--
<start-time>2003-12-17 2:15:00 pm</start-time>      
<end-time>2013-12-17 2:15:00 pm</end-time>      
-->

<cron-expression>0/15 * * ? * *</cron-expression>
<!-- every 15 seconds... -->
</cron>
</trigger>
</job>

<job>
<job-detail>
<name>testJob2</name>
<group>testJobs</group>
<description>Test Job Number 2</description>
<job-class>personal.ruanyang.quartz.plugin.SimpleJob</job-class>
<volatility>false</volatility>
<durability>false</durability>
<recover>false</recover>
</job-detail>
<trigger>
<simple>
<name>testTrigger2</name>
<group>testJobs</group>
<description>Test Trigger Number 2</description>
<calendar-name>holidayCalendar</calendar-name>
<job-name>testJob2</job-name>
<job-group>testJobs</job-group>
<start-time>2004-02-26T12:26:00</start-time>
<repeat-count>10</repeat-count>
<repeat-interval>5000</repeat-interval>
</simple>
</trigger>
</job>

</quartz>


3.Shutdown Hook(通过捕捉JVM关闭时的事件,来关闭调度器)插件:
org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownhook.cleanShutdown = true
设置RMIRMI Server Scheduler Properties
没有必需的主要属性,所有的都是合理的缺省的。通过RMI使用Quartz时,我们需要启动一个配置好了的Quartz实例来通过RMI“输出”它的服务。然后我们通过配置Quartz的调度器创建一个客户端来“代理”它连到服务器上的工作。

一些用户在客户端和服务器端经历过类可用性(jobs classes)的问题,为了解决这些问题,我们需要理解RMI的“codebase”和RMI的安全管理。以下资源在这方面会很有用:

RMI和codebase的精彩描叙:http://www.kedwards.com/jini/codebase.html  重要的一点要意识到,codebase是被客户端使用的。

安全管理的快速信息:http://gethelp.devx.com/techtips ... tions/10min0500.asp

最后读来自于java API文档的RMISecurityManager:

http://java.sun.com/j2se/1.4.2/docs/api/java/rmi/RMISecurityManager.html

属性名
需要
缺省值

org.quartz.scheduler.rmi.export
no
false

org.quartz.scheduler.rmi.registryHost
no
'localhost'

org.quartz.scheduler.rmi.registryPort
no
1099

org.quartz.scheduler.rmi.createRegistry
no
'never'

org.quartz.scheduler.rmi.serverPort
no
random

org.quartz.scheduler.rmi.proxy
no
false


org.quartz.scheduler.rmi.export
如果我们想要Quartz调度器通过RMI输出服务,那么我们就把“rmi.export”标志执为true。

org.quartz.scheduler.rmi.registryHost
能够找到的RMI注册的主机(常为“localhost”)。
org.quartz.scheduler.rmi.registryPort
RMI注册的监听端口(常为1099).
org.quartz.scheduler.rmi.createRegistry
设置“rmi.createRegistry” 依照我们想要Quartz怎样创建RMI注册。如果我们不想Quartz创建一个注册,就可以用“false”或“never”(如已经有了一个外部的注册在运行了)。如果我们想先要Quartz尝试使用一个存在的注册并且然后返回再建一个,就用“true”或者“as_needed”。如果我们想要Quartz尝试创建一个注册然后返回使用一个存在的,就用“always”。如果注册被创建,它将会绑定属性“org.quartz.scheduler.rmi.registryPort”提供的端口,“org.quartz.rmi.registryHost”应该是主机。
org.quartz.scheduler.rmi.serverPort
Quartz调度器服务将绑定和监听连接的端口。缺省的,RMI服务将随机选择一个端口。
org.quartz.scheduler.rmi.proxy
如果想要连接到远程的调度器服务,我们就要设置“org.quartz.scheduler.rmi.proxy”为true。然后必需指定一个主机和它注册了的端口号。
在同一个文件里给“org.quartz.scheduler.rmi.export”和“org.quartz.scheduler.rmi.proxy”同时设置为true并没有意义。如果你这样做的话,“export”项会被忽略。如果你没有通过RMI用Quartz,给这两项同时设置为false当然也没有用。
设置RAMJobStoreRAMJobStore用来在内存里储存调度时的信息(job,trigger,calendars)。RAMJobStore很快并且是轻量级的,但是当进程终止时所有的信息都将丢失。
通过设置“org.quartz.jobStore.class”属性来选用RAMJobStore:
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
RAMJobStore 能够通过下面的属性来调整:
属性名
需要
类型
缺省值

org.quartz.jobStore.misfireThreshold
no
int
60000


org.quartz.jobStore.misfireThreshold
在触发器被认为没有触发之前,调度器能承受一个触发器再次触发的一个毫秒级数字。

设置JDBC-JobStoreTXJobStoreTX是在每次行为(如增加一个job)之后,通过调用commit() (或者 rollback())来管理事务。如果你在一个单机应用里或者当在一个servlet容器里用Quartz而且应用没有用JTA事务时,JDBCJobStore是正确的。
JobStoreTX是通过设置“org.quartz.jobStore.class”属性来选用的:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
JobStoreTX能够通过以下属性来调整:

属性名
必须
类型
缺省值

org.quartz.jobStore.driverDelegateClass
yes
string
null

org.quartz.jobStore.dataSource
yes
string
null

org.quartz.jobStore.tablePrefix
no
string
"QRTZ_"

org.quartz.jobStore.useProperties
no
boolean
false

org.quartz.jobStore.misfireThreshold
no
int
60000

org.quartz.jobStore.isClustered
no
boolean
false

org.quartz.jobStore.clusterCheckinInterval
no
long
15000

org.quartz.jobStore.maxMisfiresToHandleAtATime
no
int
20

org.quartz.jobStore.dontSetAutoCommitFalse
no
boolean
false

org.quartz.jobStore.selectWithLockSQL
no
string
"SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE"

org.quartz.jobStore.txIsolationLevelSerializable
no
boolean
false


org.quartz.jobStore.driverDelegateClass
•org.quartz.impl.jdbcjobstore.StdJDBCDelegate (所有JDBC兼容的驱动) •org.quartz.impl.jdbcjobstore.MSSQLDelegate (Microsoft SQL Server和Sybase) •org.quartz.impl.jdbcjobstore.PostgreSQLDelegate •org.quartz.impl.jdbcjobstore.WebLogicDelegate (WebLogic驱动) •org.quartz.impl.jdbcjobstore.oracle.OracleDelegate•org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate (用在Weblogic里的Oracle驱动) •org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate (用在Weblogic里的Oracle驱动) •org.quartz.impl.jdbcjobstore.CloudscapeDelegate •org.quartz.impl.jdbcjobstore.DB2v6Delegate•org.quartz.impl.jdbcjobstore.DB2v7Delegate •org.quartz.impl.jdbcjobstore.HSQLDBDelegate •org.quartz.impl.jdbcjobstore.PointbaseDelegate
org.quartz.jobStore.misfireThreshold
同RAM
org.quartz.jobStore.clusterCheckinInterval
影响着核查出失败实例的速度。
org.quartz.jobStore.dontSetAutoCommitFalse
设置这个属性为“true”是让Quartz不去在JDBC连接上调用setAutoCommit(false)这个函数。
org.quartz.jobStore.selectWithLockSQL
在“LOCKS”表里选择一行并且锁住这行的SQL语句。缺省的语句能够为大部分数据库工作。“{0}”是在运行时你配置的表前缀。
org.quartz.jobStore.txIsolationLevelSerializable
设置“true”让Quartz(当用JobStoreTX或CMT)在JDBC连接上调用setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)。这可以阻止数据库在高加载或长时间的事务情况下的锁超时。

设置JDBC-JobStoreCMTJobStoreCMT是依赖与被用Quartz的应用管理着的事务。JTA事务必须在尝试调度(或卸载调度)jobs/triggers之前处在进程中。这允许调度工作成为应用加大事务的一部分。JobStoreCMT实际上需要用到两个数据源,一个数据源要连到被应用服务器管理的事务(通过JTA),另外一个数据源的连接在全局(JTA)事务中并不参加。当应用用JTA事务(例如通过EJB Session Beans)来执行他们的工作时,JobStoreCMT是正确的。
通过设置 'org.quartz.jobStore.class'属性来选用JobStore:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
JobStoreCMT通过以下属性来调整:
属性名
必须
类型
缺省值

org.quartz.jobStore.driverDelegateClass
yes
string
null

org.quartz.jobStore.dataSource
yes
string
null

org.quartz.jobStore.nonManagedTXDataSource
yes
string
null

org.quartz.jobStore.tablePrefix
no
string
"QRTZ_"

org.quartz.jobStore.useProperties
no
boolean
false

org.quartz.jobStore.misfireThreshold
no
int
60000

org.quartz.jobStore.isClustered
no
boolean
false

org.quartz.jobStore.clusterCheckinInterval
no
long
15000

org.quartz.jobStore.maxMisfiresToHandleAtATime
no
int
20

org.quartz.jobStore.dontSetAutoCommitFalse
no
boolean
false

org.quartz.jobStore.dontSetNonManagedTXConnectionAutoCommitFalse
no
boolean
false

org.quartz.jobStore.selectWithLockSQL
no
string
"SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE"

org.quartz.jobStore.txIsolationLevelSerializable
no
boolean
false

org.quartz.jobStore.txIsolationLevelReadCommitted
no
boolean
false


org.quartz.jobStore.dataSource
对于JobStoreCMT,数据源需要包含能够加入JTA(容器管理)事务里的连接。这就意味着数据源将在应用服务器里被配置和管理,并且,Quartz将通过JNDI获得一个句柄。

org.quartz.jobStore.nonManagedTXDataSource
JobStoreCMT需要一个数据源(以上说的第二个)连到不是容器管理的事务。这个值将是定义在配置属性文件的一个数据源名称,这个数据源必须包含非CMT的连接,换句话说,就是Quartz直接在连接上调用commit()和rollback()。
org.quartz.jobStore.dontSetNonManagedTXConnectionAutoCommitFalse
除了它应用于非TX数据源管理,其他的和org.quartz.jobStore.dontSetAutoCommitFalse一样
org.quartz.jobStore.txIsolationLevelReadCommitted
设置“true”,让Quartz在没有被管理的JDBC连接上调用setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED)。这可以阻止一些数据库(如DB2)在高加载和长时间事务的情况下发生的锁超时。
设置数据源如果你用JDBC-JobStore,你将需要一个数据源(或在JobStoreCMT里要2个)。
数据源能通过2种方法配置:
1.Quartz搜集所有指定在quartz.properties 文件里的属性来创建数据源。 2.指定一个定位于管理数据源的应用服务器的JNDI,这样Quartz能用它。
每个定义的数据源必须有个名字,你为这个数据源定义的一些属性必须包含这个名字,象下面的。数据源的“NAME”可以随便取,只有当我们把数据源赋给JDBCJobStore时,这个名字起到标示的作用,其他情况下没什么用。
Quartz自己创建数据源通过以下属性:
属性名
必须
类型
缺省值

org.quartz.dataSource.NAME.driver
yes
String
null

org.quartz.dataSource.NAME.URL
yes
String
null

org.quartz.dataSource.NAME.user
no
String
""

org.quartz.dataSource.NAME.password
no
String
""

org.quartz.dataSource.NAME.maxConnections
no
int
10

org.quartz.dataSource.NAME.validationQuery
no
String
null


org.quartz.dataSource.NAME.validationQuery
是一个可选的SQL查询字符串,数据源用它来核查和替代失败/被破坏的连接。例如,一个Oracle用户可能选择“select table_name from user_tables”-这是一个决不可能失败的查询,除非连接是坏的。
org.quartz.dataSource.myDS.driver = oracle.jdbc.driver.OracleDriver
org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@10.0.1.23:1521:demodb
org.quartz.dataSource.myDS.user = myUser
org.quartz.dataSource.myDS.password = myPassword
org.quartz.dataSource.myDS.maxConnections = 30
引用应用服务器的数据源:
属性值
必须
类型
缺省值

org.quartz.dataSource.NAME.jndiURL
yes
String
null

org.quartz.dataSource.NAME.java.naming.factory.initial
no
String
null

org.quartz.dataSource.NAME.java.naming.provider.url
no
String
null

org.quartz.dataSource.NAME.java.naming.security.principal
no
String
null

org.quartz.dataSource.NAME.java.naming.security.credentials
no
String
null


org.quartz.dataSource.NAME.java.naming.factory.initial
JNDI上下文初始化工厂的类名。
org.quartz.dataSource.NAME.java.naming.provider.url
连接到JNDI上下文的URL。
org.quartz.dataSource.NAME.java.naming.security.principal
连接到JNDI上下文的首要用户。
org.quartz.dataSource.NAME.java.naming.security.credentials
连接到JNDI上下文的用户验证密码。
org.quartz.dataSource.myOtherDS.jndiURL=jdbc/myDataSource
org.quartz.dataSource.myOtherDS.java.naming.factory.initial=
com.evermind.server.rmi.RMIInitialContextFactory
org.quartz.dataSource.myOtherDS.java.naming.provider.url=ormi://localhost
org.quartz.dataSource.myOtherDS.java.naming.security.principal=admin
org.quartz.dataSource.myOtherDS.java.naming.security.credentials=123
设置集群集群可以通过fail-over和load balancing功能给调度器带来既高可靠性又可伸缩性两大优点。

集群目前仅能和JDBC-JobStore(JobStoreTX或JobStoreCMT)一起工作,本质上是让集群的每个节点共享一个数据库来工作的。
Load-balancing是自动出现的,集群的每个节点尽可能快地触发job。当一个触发器触发时刻到了,第一个将获取触发器(并加锁)的节点就是将要触发它的节点。
Fail-over是一个节点正在执行一个或多个jobs时失败了出现的。当一个节点失败了,其他的节点就会在数据库里核查条件和鉴别jobs,这些是节点失败时记录到了数据库的。在恢复节点时,任何标记了恢复(JobDetail里的"requests recovery"属性)的jobs将会被再次执行,没有标记的将会简单地释放掉。
通过设置“org.quartz.jobStore.isClustered”属性来使用集群。在集群里每个实例应该用一样的quartz.properties文件。用到的异常也应该是一样的:不同线程池大小,不同“org.quartz.scheduler.instanceName”属性值。每个节点应该用唯一的instanceId。我们可以设置org.quartz.scheduler.instanceId的值为“AUTO”来达到这个目的。
不要在一个分离开的机器上运行集群,除非他们的时钟是用时钟同步服务同步过的。如果不熟悉怎样同步,参考:http://www.boulder.nist.gov/timefreq/service/its.htm
其他实例在用数据表时,不要触发一个不是集群的也用这些数据表的实例。你会得到一些没用的数据。

#=================================================================# Configure Main Scheduler Properties  
#=================================================================org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
#=================================================================# Configure ThreadPool  
#=================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5
#=================================================================# Configure JobStore  
#=================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
#=================================================================
# Configure Datasources  
#=================================================================
org.quartz.dataSource.myDS.driver = oracle.jdbc.driver.OracleDriver
org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@polarbear:1521:dev
org.quartz.dataSource.myDS.user = quartz
org.quartz.dataSource.myDS.password = quartz
org.quartz.dataSource.myDS.maxConnections = 5
org.quartz.dataSource.myDS.validationQuery=select 0 from dual
14.在Web应用中用Quartz初始化调度器我们可以在Web应用中的配置文件web.xml里设置一个Quartz的Servlet-QuartzInitializerServlet:
<web-app>


<servlet>
<servlet-name>QuartzInitializer</servlet-name>   <display-name>Quartz Initializer Servlet</display-name><servlet-class>    org.quartz.ee.servlet.QuartzInitializerServlet  </servlet-class>    <load-on-startup>1</load-on-startup>   <init-param>    <param-name>config-file</param-name> <param-value>/some/path/my_quartz.properties</param-value>  </init-param>   <init-param>    <param-name>shutdown-on-unload</param-name>    <param-value>true</param-value>  </init-param>   <init-param>    <param-name>start-scheduler-on-load</param-name> <param-value>true</param-value>  </init-param>  </servlet>   <!-- other web.xml items here --> </web-app>
说明:config-file参数值是StdSchedulerFactory用来实例化调度器的,可以把自己写的Quartz属性文件放在classPath即WEB-INF/classes路径下。

访问调度器从Quartz1.5开始,QuartzInitializerServlet将自动储存StdSchedulerFactory实例在ServletContext里:

// 从Session中获得ServletContext
ServletContext ctx =
request.getSession().getServletContext();
// 从ServletContext中获得StdSchedulerFactory
StdSchedulerFactory factory = (StdSchedulerFactory)ctx.getAttribute(
QuartzFactoryServlet.QUARTZ_FACTORY_KEY);
// 从StdSchedulerFactory中获得Scheduler
Scheduler scheduler = factory.getScheduler();
// 启动Scheduler
scheduler.start();

FAQ1.       怎样控制Job实例?

看看org.quartz.spi.JobFactory 和 the org.quartz.Scheduler.setJobFactory(..) 方法。



2.       在一个job完成之后,我怎样阻止它被删掉?

设置JobDetail.setDurability(true)-当job是一个“孤儿”(没有trigger引用这个job)时,这将指示Quartz不要删掉它。



3.       怎样阻止job并行触发?

使job类实现StatefulJob接口而不是job接口。察看StatefulJob 的JavaDoc。



4.       怎样使一个正在执行的job停下来?

看看org.quartz.InterruptableJob接口和Scheduler.interrupt(String, String)方法。


5.       怎样使Jobs的执行串联起来?
有两个方法:
一、用监听器
二、用JobDataMap



6.       怎样提高JDBC-JobStore的性能?
除了硬件的提高外,我们可以给我们建的Quartz表建索引:
create index idx_qrtz_t_next_fire_time on qrtz_triggers(NEXT_FIRE_TIME);
create index idx_qrtz_t_state on qrtz_triggers(TRIGGER_STATE);
create index idx_qrtz_t_nf_st on qrtz_triggers(TRIGGER_STATE,NEXT_FIRE_TIME);
create index idx_qrtz_ft_trig_name on qrtz_fired_triggers(TRIGGER_NAME);
create index idx_qrtz_ft_trig_group on qrtz_fired_triggers(TRIGGER_GROUP);
create index idx_qrtz_ft_trig_name on qrtz_fired_triggers(TRIGGER_NAME);
create index idx_qrtz_ft_trig_n_g on
qrtz_fired_triggers(TRIGGER_NAME,TRIGGER_GROUP);
create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(INSTANCE_NAME);
create index idx_qrtz_ft_job_name on qrtz_fired_triggers(JOB_NAME);
create index idx_qrtz_ft_job_group on qrtz_fired_triggers(JOB_GROUP);
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 06-将整型值转换为字符串(字符串处理)

    StringUtil.java package com.lh.bean; public class StringUtil {// 转换前的int值private int intValue = 0;// 转换后的字符串1值private String strValue1;// 转换后的字符串2值private String strValue2;// 转换后的字符串3值private String strValue3;// 默认构造方法pub…...

    2024/4/21 0:54:30
  2. golang字符串和整型互转

    在golang语言中字符串和整数之间的转换相比PHP有点复杂。刚学习的人,尤其学过PHP,秒级可以搞定的事情,这里却要使用strcov包中函数转换。 没办法入了golang的大门,就要继续探究下去。1.字符串转成整型func Atoi(s string) (int, error)//举例v := "10"if s, err …...

    2024/4/21 0:54:29
  3. springBoot-Quartz 定时任务

    1.1 Quartz 概述 Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。该项目于 2009 年被 Terracotta 收购,目前是 Terracotta 旗下的一个项目。读者可以到 http://www.quartz-scheduler.org/站点下载 Quartz 的发布版本及其源代码。 1.2 Qua…...

    2024/4/21 0:54:28
  4. 一文教你秒懂晶体三极管与场效应晶体管选型的诀窍

    在电子元件行业,晶体三极管与场效应晶体管都是备受推崇的两种电子元件,尤其在开关电源方面备受电子工程师的青睐,可是对于刚入门的采购,究竟该如何去选晶体三极管与场效应晶体管,晶体三极管简称三极管,和场效应晶体管一样,具有放大作用和开关特性的,是电子设备中的核心器…...

    2024/4/21 0:54:27
  5. C语言---整型字符串转换

    C语言提供了几个标准库函数,可以将任意类型(整型、长整型、浮点型等)的数字转换为字符串。以下是用itoa()函数将整数转 换为字符串的一个例子:# include <stdio.h> # include <stdlib.h>void main (void) { int num = 100; char str[25]; itoa(nu…...

    2024/5/5 17:40:00
  6. 【Quartz】Quartz存储与持久化-基于Spring的配置

    林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka 在上文【Quartz】Quartz存储与持久化-基于quartz.properties的配置 ,是通过配置quartz.properties文件的方式来实现持久化的。本文将通过Spring配置的方式来实现存储与持久化。本文工程免费…...

    2024/4/21 0:54:25
  7. 三极管稳压线性电源

    本文将为大家讲解下由分立元件搭成的线性电源,其基本电路拓扑如图1所示: 图1 其稳压原理:由电阻R1和稳压管D1组成基本的稳压电路,稳压管上得到一个稳定的电压,如果是5V6的稳压管就得到5V6电压,稳压管再和三极管基极连接,发射极输…...

    2024/4/21 0:54:24
  8. mysql字符串和整型之间的转换

    mysql 字符串转换为整型 :CAST(varchar AS UNSIGEND ) ORDER BY 整型转换为字符串:CONCAT (varchar,vachar1) 完成字符串的拼接 注:UNSIGEND 类型 整型的每一种都分有无符号(unsigned)和有符号(signed)两种类型(float和double总是带符号的),在默认情况下声明的整…...

    2024/4/21 0:54:23
  9. Spring4+Quartz2集群动态创建任务

    公司最近需要使用Quartz集群来实现任务的动态创建和删除,之前自己只是用过配置好的单机版的,而且是定时 执行的任务,正好借这个机会深入学习一下Quartz。在正式开始之前,我们先来了解下,spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会…...

    2024/4/20 20:54:41
  10. 三极管电路必懂的几种分析方法

    之前给大家分享过关于三极管的文章《三极管来源,及NPN与PNP区别》,今天继续分享相关内容。三极管有静态和动态两种工作状态。未加信号时三极管的直流工作状态称为静态,此时各极电流称为静态电流,给三极管加入交流信号之后的工作电流称为动态工作电流,这时三极管是交流工作…...

    2024/4/20 20:54:41
  11. 随笔--C、C++整型,长整型与字符串之间的相互转换

    1.__int64 转化为字符串char ch[128];__int64 m = 9899;_i64toa_s(m,ch,128,10); //128 表示字节数,10表示十进制std::string tempStr = ch;//tempStr存储着 字符串“9899”2.字符串与字符串之间赋值char ch1[128];char ch2[128];strcpy(ch1,"1111111111111111");st…...

    2024/4/20 20:54:38
  12. springboot-Quartz 集成源码分析和demo

    springboot-Quartz 集成源码跟踪 在pom.xml里加入 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId> </dependency>利用starter的原理在 spring.factories里有 org.springfr…...

    2024/4/20 20:54:37
  13. 整型变量转换为字符串变量(myitoa)

    将整型变量转换为字符串变量 最近刷编程题,总是有统计数字类型的题目。于是想出将整型转换为字符串,再逐一寻找的暴力做法,但怎样将整型变量转换为字符串变量呢,C中头文件里有atoi现成的函数可以使用,倔强的自己非要自己写一个,同样简单粗暴方法 #include<iostream>…...

    2024/4/20 20:54:36
  14. DS18B20工作原理

    下面简单介绍一下ds18b20的东西吧1.DS18B20是Dallas公司生产的数字温度传感器,具有体积小、适用电压宽、经济灵活的特点。它内部使用了onboard专利技术,全部传感元件及转换电路集成在一个形如三极管的集成电路内。DS18B20有电源线、地线及数据线3根引脚线,工作电压范围为3~…...

    2024/4/20 20:54:35
  15. SpringBoot Quartz指定时间执行任务及取消该定时任务

    SpringBoot Quartz指定时间执行任务及取消未执行的定时任务Quartz指定时间执行任务一:导入依赖二:实例化需要定时的任务三:构建一个JobBuilder的实例四:**编写触发器**五:通过Scheduler调度器来调度取消未执行的定时任务如何向execute方法里传参 之前都是使用quartz实现周…...

    2024/5/5 17:06:31
  16. DSP TMS320C6000基础学习(1)——介绍

    主要内容1. Why process signals digitally? (1)模拟电路由模拟组件构成:电阻、电容及电感等,这些组件随着电压、温度或机械结构的改变会动态影响到模拟电路的效果; (2)数字电路具有好的噪声抑制能力,少的开发时间和功耗 虽然数字电路有那么多优点,在有些情况下还必须…...

    2024/4/20 20:54:33
  17. 三极管开关电路

    三极管除了可以当做交流信号放大器之外,也可以做为开关使用。严格说起来,三极管与一般的机械接点式开关在动作上并不完全相同,但是它却具有一些机械式开关所没有的特点。图1所示,即为三极管电子开关的基本电路图。由下图可知,负载电阻被直接跨接于三极管的集电极与电源之间…...

    2024/4/21 0:54:22
  18. C++ 整型和字符串相互转换(转载)

    itoa功 能:把一整数转换为字符串用 法:char *itoa(int value, char *string, int radix);详细解释:itoa是英文integer to array(将int整型数转化为一个字符串,并将值保存在数组string中)的缩写.参数:value: 待转化的整数。radix: 是基数的意思,即先将value转化为radix进制的数…...

    2024/4/21 0:54:21
  19. Quartz的负载均衡如何实现

    项目中使用Quartz来管理定时任务,配置将任务信息保存到关系型数据库中,并且使用的是集群模式。集群会保证同一个任务到达触发时间的时候,只有一台机器去执行该任务。我现在想了解的是:1.Quartz如何保证任务只在一个节点运行(即任务不会重复执行)?2.在集群的哪个节点上运行…...

    2024/4/21 0:54:21
  20. quartz多任务调度+spring 实现

    转自:http://www.cnblogs.com/MrRightZhao/p/7986727.html一.Quartz的学习简述  客官,不要急,请看完下面的内容...  代码可以直接拷贝使用,本文是编写2个定时方法来实现的,如果想要执行1个,删除另1个即可。但是想要知道执行原理请看最后的原理分析二.执行任务类 1 pa…...

    2024/4/21 0:54:20

最新文章

  1. 一些CoAP协议面试题

    请简要介绍CoAP协议及其在物联网中的角色。 答案&#xff1a;CoAP是一种专为物联网设备设计的轻量级应用层协议&#xff0c;特别适用于资源受限的设备&#xff0c;如传感器和嵌入式系统。它在物联网中扮演的角色主要是实现这些设备之间的通信&#xff0c;通过简单的RESTful接口…...

    2024/5/5 18:38:27
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 鲨鱼恐怖的第六感

    除了视觉、嗅觉、听觉、味觉、触觉这五种感官&#xff0c; 鲨鱼还有敏锐的「第六感」&#xff1a;电觉&#xff0c;可以侦测微弱电场&#xff0c;捕捉猎物。 恐怖的背鳍划破水面&#xff0c;直逼我们而来─一头三公尺长的硕大青鲨&#xff0c;正如鱼雷般朝血腥气味方向游去。…...

    2024/4/30 1:03:11
  4. ssm框架中各层级介绍

    1、Spring&#xff08;业务逻辑层&#xff09;&#xff1a; Spring框架提供了依赖注入&#xff08;DI&#xff09;和面向切面编程&#xff08;AOP&#xff09;等功能&#xff0c;可以帮助管理Java应用程序中的对象依赖关系和提供横切关注点的支持。 在SSM框架中&#xff0c;S…...

    2024/5/3 3:42:05
  5. 小林coding图解计算机网络|基础篇01|TCP/IP网络模型有哪几层?

    小林coding网站通道&#xff1a;入口 本篇文章摘抄应付面试的重点内容&#xff0c;详细内容还请移步&#xff1a; 文章目录 应用层(Application Layer)传输层(Transport Layer)TCP段(TCP Segment) 网络层(Internet Layer)IP协议的寻址能力IP协议的路由能力 数据链路层(Link Lay…...

    2024/5/5 8:35:23
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/4 23:54:56
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/4 23:55:17
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/4 18:20:48
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/4 23:55:06
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/4 23:55:01
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57