转载

quartz的简单介绍及应用

今天有一个任务需要定时执行,考虑了几个方法:

(1)python或者shell写一些脚本,然后crontab方法

(2)Spring+JDK Timer

想想上个项目使用的是第二种情况的,实际使用中存在了诸多的问题,比如

  • 步骤复杂、分散
  • 使用写死服务器Host的方式执行task,存在单点风险,负载均衡手动完成。
  • 应用重启,任务无法自动恢复

在应用过程中十分痛苦,最近重新搜了一下,发现一个更加好用的工具:Quartz ! 这个工具在美团中的有大量使用,详见他们的官方博客: http://tech.meituan.com/mt-crm-quartz.html。

光看博客对它有个了解,但是我们还是从官方文档-2.2版本的html文档( https://quartz-scheduler.org/generated/2.2.2/html/qtz-all/#page/quartz-scheduler-webhelp%2Fto-quartz_scheduler_online_documentation_library.html)来学习这个强大的工具。

首先,对quartz有个大致了解,

Quartz是Java领域最著名的开源任务调度工具。Quartz提供了极为广泛的特性如持久化任务,集群和分布式任务等,其特点如下:

  • 完全由Java写成,方便集成(Spring)
  • 伸缩性
  • 负载均衡
  • 高可用性

更多详情还是移步官方网站吧( https://quartz-scheduler.org/)

下面我们以实际的例子来学习 在Spring中使用Quartz有两种方式实现:

- 第一种是任务类继承QuartzJobBean;

- 第二种则是在配置文件里定义任务类和要执行的方法,类和方法可以是普通类;

我们分别来看一下这两种方式:

(1)任务类继承QuartzJobBean

首相定义一个job,就是我们要具体跑的任务

package xiaolong.com.quartz.play;  import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException;  import java.util.Date;  /**  * @author zhangxiaolong  */ public class SimpleQuartzJob implements Job {  //    static Log logger = LogFactory.getLog(ScanDirectoryJob.class);//日志记录器      public SimpleQuartzJob() {     }      @Override     public void execute(JobExecutionContext context) throws JobExecutionException {         System.out.println("In SimpleQuartzJob - executing its JOB at "                 + new Date() + " by " + context.getTrigger().getDescription());     } }

然后定义定义我们的触发器trigger

package xiaolong.com.quartz.play;  import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory;  import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger;  /**  * @author zhangxiaolong  */ public class SimpleTriggerRunner {      public static void main(String[] args) {         SimpleTriggerRunner simpleTriggerRunner = new SimpleTriggerRunner();          try {             Scheduler scheduler = simpleTriggerRunner.createScheduler();             simpleTriggerRunner.scheduleJob(scheduler);              scheduler.start();         } catch (SchedulerException e) {             e.printStackTrace();         }     }      public Scheduler createScheduler() throws SchedulerException {         // 创建调度器         return StdSchedulerFactory.getDefaultScheduler();     }      //Create and Schedule a ScanDirectoryJob with the Scheduler     private void scheduleJob(Scheduler scheduler) throws SchedulerException     {         // Create a JobDetail for the Job         JobDetail jobDetail = newJob(SimpleQuartzJob.class).withIdentity("myJob","group1").build();  //        Date runTime = evenMinuteDate(new Date());          Trigger trigger = newTrigger().withIdentity("myTrigger","group1").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(5).withRepeatCount(10)).build(); //        Trigger trigger = newTrigger().withIdentity("myTrigger","group1").startAt(RunTime).build();          scheduler.scheduleJob(jobDetail, trigger);     }  }

最后,我们简单用main方法来调用定时任务;

当然触发器还有一种类似于crontab的方式,即

package xiaolong.com.quartz.play;  import org.quartz.*; import org.quartz.impl.StdSchedulerFactory;  import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger;  /**  * @author zhangxiaolong  */ public class CronTriggerRunner {      public static void main(String[] args) {          CronTriggerRunner cronTriggerRunner = new CronTriggerRunner();         try {             cronTriggerRunner.createScheduler();             cronTriggerRunner.scheduleJob2(cronTriggerRunner.getScheduler());             cronTriggerRunner.start();          } catch (SchedulerException e) {             e.printStackTrace();         }      }      private void start() {         if (null != scheduler) {             try {                 if (scheduler.isStarted()) {                     System.out.println("has started!");                 }                 scheduler.start();             } catch (SchedulerException e) {                 e.printStackTrace();             }         }     }      private Scheduler scheduler;      public void createScheduler() throws SchedulerException {         // 创建调度器         scheduler = StdSchedulerFactory.getDefaultScheduler();     }      private void scheduleJob(Scheduler scheduler) throws SchedulerException     {         JobDetail jobDetail = newJob(SimpleQuartzJob.class).withIdentity("myJob2","group1").build();          CronTrigger trigger = newTrigger().withIdentity("myTrigger2","group1").withSchedule(cronSchedule("0/5 * * * * ?")).build();          scheduler.scheduleJob(jobDetail, trigger);     }      private void scheduleJob2(Scheduler scheduler) throws SchedulerException     {         JobDetail jobDetail = newJob(SimpleQuartzJob.class).withIdentity("myJob2","group1").build();          Trigger trigger = newTrigger().withIdentity("myTrigger3","group1").withSchedule(cronSchedule("0/1 * * * * ?")).build();          scheduler.scheduleJob(jobDetail, trigger);     }      private void stop() {         if (null != scheduler) {             try {                 if (!scheduler.isShutdown()) {                     scheduler.shutdown(true);                 }             } catch (SchedulerException e) {                 e.printStackTrace();             }         }     }      public Scheduler getScheduler() {         return scheduler;     }      public void setScheduler(Scheduler scheduler) {         this.scheduler = scheduler;     } } 

(2)在配置文件里定义任务类和要执行的方法,类和方法可以是普通类 在spring的框架中编写一个xml文件, “` xml <?xml version= 1.0 encoding= UTF-8 ?>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">     <property name="triggers">         <list>             <ref bean="autoMatchJobTrigger"/>         </list>     </property>     <property name="autoStartup" value="true"/> </bean>  <bean id="autoMatchJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">     <property name="jobDetail" ref="autoMatchJob"/>     <!-- 每隔1小时触发一次 -->     <property name="cronExpression" value="0 30 20 ? * *"/> </bean>  <bean id="autoMatchJob"       class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">     <property name="targetObject" ref="autoMatchTask"/>     <property name="targetMethod" value="autoMatching"/>      <!-- 是否允许任务并发执行。当值为false时,表示必须等到前一个线程处理完毕后才再启一个新的线程 -->     <property name="concurrent" value="false"/> </bean>  <bean id="autoMatchTask" class="com.baijia.accounting.quartz.AutoMatchingTask">     <property name="start" value="${autoMatchingHolderTask.start:true}"/> </bean>

配置的内容呢,就是按照quartz的流程去配置一下job、trigger、调度器等等,

具体的任务呢,就可以是

public class AutoMatchingTask {      private static final Logger logger = LoggerFactory.getLogger(AutoMatchingTask.class);      private static ExecutorService es = Executors.newSingleThreadExecutor();      private boolean start;      public void setStart(boolean start) {         this.start = start;     }      public void autoMatching() {      do something… }

(完)

原创文章,转载请注明:转载自时间记忆

本文链接地址: quartz的简单介绍及应用

正文到此结束
Loading...