>> 在spring中使用quartz
创建JobDetailBean:
1
2
3
4
5
6
7
8
9
10
|
<!-- 通过JobDetailBean实现 -->
<bean name=
"jobDetail"
class
=
"org.springframework.scheduling.quartz.JobDetailBean"
p:jobClass=
"com.baobaotao.quartz.MyJob"
p:applicationContextJobDataKey=
"applicationContext"
>
<property name=
"jobDataAsMap"
>
<map>
<entry key=
"size"
value=
"10"
/>
</map>
</property>
</bean>
|
在JobDetailBean中有几个属性:
jobClass:类型为Class,实现了Job接口的任务类
beanName:显示指定Bean名称,没啥用处
jobDataAsMap:类型为Map,为任务所对应的JobDataMap提供值。
applicationContextJobDataKey:用户可以通过这个key值将Spring的ApplicationContext的引用保存在里面。
jobListenerNames:类型为String[],指定注册在Schedule中的JobListeners名称。
下面是MyJob定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import
java.util.Map;
import
org.quartz.JobExecutionContext;
import
org.quartz.JobExecutionException;
import
org.quartz.StatefulJob;
import
org.springframework.context.ApplicationContext;
public
class
MyJob
implements
StatefulJob {
public
void
execute(JobExecutionContext jctx)
throws
JobExecutionException {
// Map dataMap = jctx.getJobDetail().getJobDataMap();
Map dataMap = jctx.getTrigger().getJobDataMap();
String size =(String)dataMap.get(
"size"
);
ApplicationContext ctx = (ApplicationContext)dataMap.get(
"applicationContext"
);
System.out.println(
"size:"
+size);
dataMap.put(
"size"
,size+
"0"
);
String count =(String)dataMap.get(
"count"
);
System.out.println(
"count:"
+count);
}
}
|
如果MyJob实现的是StatefulJob,那么里面的JobDataMap为共享公共变量,下次执行的时候还可以获得同样的,这个不是线程安全的,最好都用无状态的Job
>> 利用MethodInvokingJobDetailFactoryBean直接将某个bean的方法定义成任务执行的动作,也就是说不需要定义JobDetail了,直接将某个bean的方法变成job的execute方法:
1
2
3
4
5
6
|
<!-- 通过封装服务类方法实现 -->
<bean id=
"jobDetail_1"
class
=
"org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
p:targetObject-ref=
"myService"
p:targetMethod=
"doJob"
p:concurrent=
"false"
/>
<bean id=
"myService"
class
=
"com.baobaotao.service.MyService"
/>
|
>> 创建Trigger:
* SimpleTriggerBean
1
2
3
4
5
6
7
8
9
|
<bean id=
"simpleTrigger"
class
=
"org.springframework.scheduling.quartz.SimpleTriggerBean"
p:jobDetail-ref=
"jobDetail"
p:startDelay=
"1000"
p:repeatInterval=
"2000"
p:repeatCount=
"100"
>
<property name=
"jobDataAsMap"
>
<map>
<entry key=
"count"
value=
"10"
/>
</map>
</property>
</bean>
|
SimpleTriggerBean在SimpleTrigger基础上增加了以下属性:
jobDetail:对应的JobDetail
beanName:默认为bean的id,不过之前用beanName属性显示指定了名称的也可以用这个
jobDetailAsMap:以Map类型为Trigger关联的JobDataMap提供值
startDelay:延迟多少时间触发,单位为毫秒,默认为0
triggerListenerNames:类型为String[],不解释了
>> CronTriggerBean
1
2
3
4
|
<bean id=
"checkImagesTrigger"
class
=
"org.springframework.scheduling.quartz.CronTriggerBean"
p:jobDetail-ref=
"jobDetail"
p:cronExpression=
"0/5 * * * * ?"
/>
|
>> 创建Scheduler
spring提供了ScheduleFactoryBean,可以在spring容器启动后,Scheduler自动开始工作,而在spring容易关闭前,自动关闭Scheduler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<bean id=
"scheduler"
class
=
"org.springframework.scheduling.quartz.SchedulerFactoryBean"
>
<property name=
"triggers"
>
<list>
<ref bean=
"simpleTrigger"
/>
</list>
</property>
<property name=
"schedulerContextAsMap"
>
<map>
<entry key=
"timeout"
value=
"30"
/>
</map>
</property>
<property name=
"configLocation"
value=
"classpath:com/baobaotao/quartz/quartz.properties"
/>
<property name=
"quartzProperties"
>
<props>
<prop key=
"org.quartz.threadPool.class"
>
org.quartz.simpl.SimpleThreadPool
</prop>
<prop key=
"org.quartz.threadPool.threadCount"
>
10
</prop>
</props>
</property>
</bean>
|
SchedulerFactoryBean还拥有一些常见的属性:
* calendars:类型为Map,通过该属性向Scheduler注册Calendar
* jobDetails:类型为JobDetail[],注册JobDetail
* autoStartup:是否马上启动Scheduler,默认为true
* startupDelay:延迟多少秒启动Scheduler
* dataSource:当需要数据库持久化任务调度数据时候用到
* transactionManager:当配一个dataSource后,应该同步配置这个
* nonTransactionalDataSource:无事务的数据源
* quartzProperties:允许用户在spring中定义Quartz属性,覆盖quartz.properties文件中的定义
>> spring对于JDK5中的Executor的支持
JDK5本身提供的ThreadPoolExecutor类实现了Executor和ExecutorService这两个接口,它使用一个线程池对提交的任务进行调度,对于需要处理数量巨大的短小并发任务如Web服务器、数据库服务器、邮件服务器之类的应用程序需要处理大量来自远程的大量短小任务,采用线程池可以带来明显好处。
ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类,并实现了ScheduledExecutorService接口,添加了对任务的调度功能,该类明显优于JDK1.3中的Timer,因为在内部用线程池,对每次到来的任务用一个新线程去执行,而不是像TImer那么,要等这个任务执行完,才能执行下一个任务,很好的解决了Timer经常出现的时间漂移、任务挤压等问题。
工厂类Executors有很多方法很方便的创建这些线程池:
* public static ExecutorService newFixedThreadPool(int nThreads):固定数目的线程数量
* public static ExecutorService newCachedThreadPool():线程池动态的,不够就创建新的,长时间不用就回收
* public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) :创建一个线程池,可以在指定延迟后运行或定期执行任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import
org.springframework.core.task.SimpleAsyncTaskExecutor;
import
org.springframework.core.task.TaskExecutor;
public
class
ExecutorExample {
private
TaskExecutor executor;
public
void
setExecutor(TaskExecutor executor) {
this
.executor = executor;
}
public
void
executeTasks() {
for
(
int
i =
0
; i <
6
; i++) {
executor.execute(
new
SimpleTask(
"task"
+ i));
}
}
public
static
void
main(String[] args) {
ExecutorExample ee =
new
ExecutorExample();
ee.setExecutor(
new
SimpleAsyncTaskExecutor());
ee.executeTasks();
}
}
class
SimpleTask
implements
Runnable {
private
String taskName;
public
SimpleTask(String taskName) {
this
.taskName = taskName;
}
public
void
run() {
System.out.println(
"do "
+ taskName +
"... in Thread:"
+ Thread.currentThread().getId());
}
}
|
转自:http://yidao620c.iteye.com/blog/1844746