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(有狀態的),此時的任務也就會串行執行了。