Quartz任务能够静态配置到配置文件中,也能够动态添加.java
其中 <property name="concurrent" value="false"/>,是设置job不能并发执行。spring
<!-- 删除旧数据定时任务 --> <!-- 删除新闻数据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---------------------"); } }
定时器动态添加任务类app
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); } } }
测试动态定时任务添加框架
任务类less
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!!!"); } }
测试类,须要使用ide
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框架中防止任务并行能够有两种方案:spa
一、若是是经过MethodInvokingJobDetailFactoryBean在运行中动态生成的Job,配置的xml文件有个concurrent属性,这个属性的功能是配置此job是否能够并行运行,若是为false则表示不能够并行运行,不然能够并行。若是一个job的业务处理发费的时间超过了job的启动的间隔时间(repeatInterval),这个属性很是有用。若是为false,那么,在这种状况下,当前job还在运行,那么下一个job只能延时运行。若是为true,那么job就会并行运行。code
二、若是是经过自定义要执行的任务的类的名称实现job的话,则有另外一种方式:
默认的任务的类实现org.quartz.Job接口,此时任务是stateless(无状态的),即会出现并行的状况,那么如何避免这种状况发生呢?
解决方案:使QuartzJobBean类实现org.quartz.StatefulJob接口便可(StatefulJob接口仅仅是扩展了 Job 接口,未加入新的方法,能够不需实现Job接口了),那么此时任务就会变成stateful(有状态的),此时的任务也就会串行执行了。