Quartz是Java比较流行的定时任务框架,使用定时任务最烦的是不受控制的多线程,定时任务被重复执行。如何控制Quartz让定时任务不被重复执行呢?总结了3中方法和大家分享。
1. ##修改Quartz的默认线程数,从默认10个线程改为1个线程。
配置如下:
schedulerFactoryBean添加属性:configLocation。quartz.properties在Quartz.jar包中拷贝。
<bean id="schedulerFactoryBean"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger">ref>
list>
property>
<property name="configLocation" value="classpath:quartz.properties">property>
bean>
quartz.properties配置
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 1
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
2. MethodInvokingJobDetailFactoryBean的concurrent属性设值为false
<bean id="myJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="mySchedule">property>
<property name="targetMethod" value="jobHandler">property>
<property name="concurrent" value="false">property>
bean>
3. 多个待执行任务分别封装初始化时入队,执行时出队。
例如这样:
public AdapterJob() {
super();
System.out.println("AdapterJob 初始化");
//初始化一个队列
queue = new LinkedBlockingDeque<Integer>();
for (int i = 0; i < 50; i++) {
queue.offer(i);
}
startTime = System.currentTimeMillis();
}
public void jobHandler() {
String name = Thread.currentThread().getName();
System.out.println(name);
int i = queue.poll();
System.out.println(i);
}
运行效果
总结
以上3种措施一般使用一种就可以保证任务只执行一次,在一些可靠性要求高的定制任务执行场景可以考虑3中措施同时上,数据库的操作加并发锁。