美文网首页
Quartz-为应用指定不同的Scheduler

Quartz-为应用指定不同的Scheduler

作者: Teddy_b | 来源:发表于2020-07-28 19:04 被阅读0次

    一、背景

    在项目中需要定时的往Kafka中推送数据,但是推送的数据分为两类:一类是基础数据;另一类是配置数据;实现上打算使用Quartz来完成,Quartz是什么不是这篇文章的重点,本文的重点是如何在Quartz中为这两类数据指定不同的Scheduler,让这两类数据使用不同的线程池去定时推送数据。(通过实验,发现如果使用同一个Scheduler,那么这两类数据会使用同一个线程池中的线程去推送数据)

    二、实施过程

    2.1 引入依赖

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-quartz</artifactId>
                <version>2.1.1.RELEASE</version>
            </dependency>
    

    2.2 为两类数据分别定义两个Job

    定义第一个Job:

    @Component
    public class FirstJob implements Job {
            @Override
            public void execute(JobExecutionContext context) throws JobExecutionException {
                   // 在这里补充需要定时执行的任务
                   sendMessage();
           }
    }
    

    定义第二个Job:

    @Component
    public class SecondJob implements Job {
            @Override
            public void execute(JobExecutionContext context) throws JobExecutionException {
                   // 在这里补充需要定时执行的任务
                   sendMessage();
           }
    }
    

    2.3 分别为两类数据定义 JobDetail、CronTrigger以及Scheduler

    第一类数据的JobDetail、CronTrigger以及Scheduler:

    @Component
    public class FirstSender {
    
    //这里通过读取配置文件来获取定时时间
    @Value("${cronExp}")
    private String cronExp;
    
        public void schedulerFirst() throws SchedulerException {
            try {
                 // 构建JobDetail,注意这里withIdentity方法中的名称需要唯一
                JobDetail jobDetail = JobBuilder.newJob(FirstJob.class).withIdentity("firstJob").build();
                
                // 构建CronTrigger,注意这里的withIdentity中的名称和group名称要唯一
                CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("firstTrigger", "first")
                        .withSchedule(cronSchedule(cronExp))
                        .build();
               
                // 创建Scheduler,这里通过StdSchedulerFactory来创建
                StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
                Properties props = new Properties();
                props.put("org.quartz.threadPool.threadCount", "10");
                schedulerFactory.initialize(props);
                Scheduler scheduler = schedulerFactory.getScheduler();
                scheduler.scheduleJob(jobDetail, cronTrigger);
                scheduler.start();
            } catch (Exception e) {
                log.error("FirstSender start failure!", e);
            }
        }
    }
    

    第二类数据的JobDetail、CronTrigger以及Scheduler:

    @Component
    public class SecondSender{
    
        @Autowired
        private SchedulerFactoryBean schedulerFactoryBean;
        
        @Value("${cronExp}")
        private String cronExp;
    
        public void schedulerSecond() throws SchedulerException {
            try {
                 // 构建JobDetail,注意这里withIdentity方法中的名称需要唯一
                JobDetail jobDetail = JobBuilder.newJob(QuartsConfigJob.class).withIdentity("second").build();
                
                 // 构建CronTrigger,注意这里的withIdentity中的名称和group名称要唯一
                CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("secondTrigger", "second")
                        .withSchedule(cronSchedule(cronExp))
                        .build();
    
               // 创建Scheduler,这里通过SchedulerFactoryBean来创建
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                scheduler.scheduleJob(jobDetail, cronTrigger);
                scheduler.start();
            } catch (Exception e) {
                logger.error("SecondSender start failure!", e);
            }
        }
    }
    

    特别注意:上述一定要使用两种不同的方式来创建Scheduler,否则创建出来的Scheduler是同一个,那么调度的时候两个Job会使用同一个线程池中的线程

    2.4 定义上述第二种创建Scheduler方式中的SchedulerFactoryBean的Bean

    public class BeanConfig {
    
        @Bean
        public SchedulerFactoryBean schedulerFactoryBean () {
            return new SchedulerFactoryBean();
        }
    
    }
    

    2.4 定义启动类

    定义启动类来启动定时任务:

    @Component
    public class StartupRunner implements CommandLineRunner {
    
      
        @Autowired
        private FirstSender firstSender ;
    
        @Autowired
        private SecondSender secondSender;
    
        @Override
        public void run(String... args) throws Exception {
            firstSender.schedulerFirst();
            secondSender.schedulerSecond();
        }
    
    }
    

    经过上述过程之后,在我们启动spring boot项目之后,定时任务就会开始执行:


    image.png

    其中eduler_开头的线程是第一类数据的线程池中的线程;ryBean_开头的线程是第二类数据的线程池中的线程。经过一段时间后,可以发现两个任务的线程数量均达到了我们设置的10个线程

    相关文章

      网友评论

          本文标题:Quartz-为应用指定不同的Scheduler

          本文链接:https://www.haomeiwen.com/subject/nghqrktx.html