Quartz任务可以静态配置到配置文件中,也可以动态添加.
1.Quartz任务 静态配置
其中 <property name="concurrent" value="false"/>,是设置job不能并发执行。
<!-- 删除旧数据定时任务 -->
<!-- 删除新闻数据job -->
<bean id="delOldNewsJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="deleteOldNewsJob"/>
<property name="targetMethod" value="doJob"/>
<property name="concurrent" value="false"/> <!--防止job并发执行-->
</bean>
<!-- tigger -->
<bean id="deleteOldNewsJobTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- org.springframework.scheduling.quartz.CronTriggerBean -->
<property name="jobDetail">
<ref bean="delOldNewsJobDetail"/>
</property>
<property name="cronExpression">
<!-- cron表达式 -->
<value>${delete.old.news.cron}</value>
</property>
</bean>
定时任务执行类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class DeleteOldNewsJob {
private Logger logger = LoggerFactory.getLogger(DeleteOldNewsJob.class);
@Value("${delete.old.news.job.enable}")
private boolean enabled;
@Autowired
private NewsFeedMapper newsFeedMapper;
public void doJob() {
if (!enabled) {
logger.info("delete old news job enabled = false");
return;
}
logger.info("----------------delete old news begins------------------");
newsFeedMapper.deleteOldNews();
logger.info("----------------delete old news end---------------------");
}
}
2.Quartz任务 动态添加
定时器动态添加任务类
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Service;
/**
* Quartz定时任务调度器管理类
*
*/
@Component
public class QuartzManager{
/**
* 任务组名
*/
private static final String JOB_GROUP_NAME = "PUSH_MESSAGE_JOB_GROUP";
/**
* 触发器组名
*/
private static final String TRIGGER_GROUP_NAME = "PUSH_MESSAGE_TRIGGER_GROUP";
/**
* Quartz调度器
*/
private Scheduler scheduler;
/**
* 初始化调度器
*
* @throws SchedulerException
*/
@PostConstruct
public void init() throws SchedulerException {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
scheduler = schedulerFactory.getScheduler();
}
/**
* 添加一个定时任务,使用默认的任务组名、触发器组名,触发器的名称跟任务的一样
*
* @param jobName 任务名称
* @param cls 任务
* @param time 任务执行的时间,Cron表达式
*/
@SuppressWarnings("rawtypes")
@Override
public void addJob(String jobName, Class cls, String time) {
try {
JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);
CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);
trigger.setCronExpression(time);
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 移除一个定时任务 使用默认的任务组名、触发器组名,触发器名跟任务名一致
*
* @param jobName 任务名称
*/
@Override
public void removeJob(String jobName) {
try {
scheduler.pauseTrigger(jobName, TRIGGER_GROUP_NAME);// 暂停触发器
scheduler.unscheduleJob(jobName, TRIGGER_GROUP_NAME);// 移除触发器
scheduler.deleteJob(jobName, JOB_GROUP_NAME);// 删除任务
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* 启动所有定时任务
*/
@Override
public void startJobs() {
try {
scheduler.start();
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* 关闭所有定时任务
*/
@Override
public void shutdownJobs() {
try {
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* 当关闭应用时,停止所有调度任务,并关掉调度器
*/
@PreDestroy
public void stopQuartz() {
try {
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
}
测试动态定时任务添加
任务类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class TestJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("time out!!!");
}
}
测试类,需要使用
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class QuartzTest {
@Resource
private QuartzManager manager;
@Test
public void test(){
manager.startJobs();
manager.addJob("test", TestJob.class,"*/5 * * * * ?");
while (true);
}
}
Quartz防止job并发执行
Quartz框架中防止任务并行可以有两种方案:
1、如果是通过MethodInvokingJobDetailFactoryBean在运行中动态生成的Job,配置的xml文件有个concurrent属性,这个属性的功能是配置此job是否可以并行运行,如果为false则表示不可以并行运行,否则可以并行。如果一个job的业务处理发费的时间超过了job的启动的间隔时间(repeatInterval),这个属性非常有用。如果为false,那么,在这种情况下,当前job还在运行,那么下一个job只能延时运行。如果为true,那么job就会并行运行。
2、如果是通过自定义要执行的任务的类的名称实现job的话,则有另一种方式:
默认的任务的类实现org.quartz.Job接口,此时任务是stateless(无状态的),即会出现并行的情况,那么如何避免这种情况发生呢?
解决方案:使QuartzJobBean类实现org.quartz.StatefulJob接口即可(StatefulJob接口仅仅是扩展了 Job 接口,未加入新的方法,可以不需实现Job接口了),那么此时任务就会变成stateful(有状态的),此时的任务也就会串行执行了。