美文网首页
定时任务

定时任务

作者: 超级笔记本 | 来源:发表于2020-05-22 16:13 被阅读0次

    Schedule

    1、注意事项

    1. @Scheduled(cron = "0/5 * * * * ?") 注解方法
    2. @EnableScheduling 注解启动类
    3. 如果是@Service中的方法,引入 import org.springframework.stereotype.Service; 不是dubbo的
    4. 适合简单的定时任务,过多的任务可能导致阻塞,崩溃,延迟启动等问题。

    2、表达式

    1010726-20190919020734351-1528359096.png

    Quartz

    1、基本要素

    1. Scheduler:调度器。所有的调度都是由它控制。
    2. Trigger: 触发器。决定什么时候来执行任务。
    3. JobDetail & Job: JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。使用JobDetail + Job而不是Job,这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

    2、引入依赖

           <dependency>
              <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.2.3</version>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz-jobs</artifactId>
                <version>2.2.3</version>
            </dependency>
    

    3、持久化配置(系统重启,自动查询数据库中的任务来启动)

    [quartz官网地址,下载压缩包,找到sql文件]{http://www.quartz-scheduler.org/downloads/}

    2018091618442589.png
    spring:
      quartz:
        #相关属性配置
        properties:
          org:
            quartz:
              scheduler:
                #调度器实例名称
                instanceName: clusteredScheduler
                #调度器实例编号自动生成
                instanceId: AUTO
              jobStore:
                #持久化方式配置
                class: org.quartz.impl.jdbcjobstore.JobStoreTX
                #持久化方式配置数据驱动,MySQL数据库
                driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
                #quartz相关数据表前缀名
                tablePrefix: QRTZ_
                #开启分布式部署
                isClustered: true
                #分布式节点有效性检查时间间隔,单位:毫秒
                clusterCheckinInterval: 10000
                #配置是否使用
                useProperties: false
              threadPool:
                #线程池实现类
                class: org.quartz.simpl.SimpleThreadPool
                #执行最大并发线程数量
                threadCount: 10
                #线程优先级
                threadPriority: 5
                #配置是否启动自动加载数据库内的定时任务,默认true
                threadsInheritContextClassLoaderOfInitializingThread: true
        #数据库方式
        job-store-type: jdbc
        #初始化表结构
        jdbc:
          initialize-schema: always
    

    4、实现Job接口

    1. 执行任务处理
    public class BaseJob implements Job {
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            //todo
        }
    }
    
    1. 反射方式调用方法
        //同一个容器中 注入applicationContext
        @Autowired
        private ApplicationContext applicationContext;
        ···
        Object service = applicationContext.getBean(serviceName)
        ···
        //不同一个容器中 注入registryConfig
        @Autowired
        private RegistryConfig registryConfig;
        ···
        ReferenceBean referenceBean = new ReferenceBean();
        referenceBean.setRegistry(registryConfig);
        referenceBean.setInterface(serviceName);
        Object service = referenceBean.getObject();
    

    5、任务管理类

    在处理自己的业务同时,调用管理类进行任务管理,比如记录日志

    package com.firstniu.venus.quartz.utils;
    
    import org.quartz.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.util.Map;
    
    /**
     * 定时任务管理类
     */
    @Component
    public class QuartzManager {
        /**
         * 注入任务调度器
         */
        @Autowired
        private Scheduler scheduler;
    
        /**
         * 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名  (带参数)
         *
         * @param jobName 任务名
         * @param cls     任务
         * @param time    时间设置,参考quartz说明文档
         */
        public void addJob(String jobName, String jobGroup, Class<? extends Job> cls, String time, Map<String, Object> param) {
            try {
                JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, jobGroup).build();    //用于描叙Job实现类及其他的一些静态信息,构建一个作业实例
                jobDetail.getJobDataMap().putAll(param);                                 //传参数
                CronTrigger trigger = TriggerBuilder
                        .newTrigger()                                                                        //创建一个新的TriggerBuilder来规范一个触发器
                        .withIdentity(jobName, jobGroup)                                            //给触发器起一个名字和组名
                        .withSchedule(CronScheduleBuilder.cronSchedule(time))
                        .build();
                scheduler.scheduleJob(jobDetail, trigger);
                if (!scheduler.isShutdown()) {
                    scheduler.start();      // 启动
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
    
        /**
         * 修改一个任务的触发时间(触发器名,触发器组名)
         *
         * @param jobName
         * @param jobGroup
         * @param time
         * @param param
         */
        public void modifyJobTime(String jobName, String jobGroup, String time, Map<String, Object> param) {
            try {
                TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);        //通过触发器名和组名获取TriggerKey
                CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);                //通过TriggerKey获取CronTrigger
                if (trigger == null) {
                    return;
                }
                trigger.getJobDataMap().putAll(param);
                String oldTime = trigger.getCronExpression();
                if (!oldTime.equalsIgnoreCase(time)) {
                    JobKey jobKey = JobKey.jobKey(jobName, jobGroup);                        //通过任务名和组名获取JobKey
                    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                    Class<? extends Job> objJobClass = jobDetail.getJobClass();
                    removeJob(jobName, jobGroup);
                    addJob(jobName, jobGroup, objJobClass, time, param);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 修改一个任务的触发时间
         *
         * @param triggerName      任务名称
         * @param triggerGroupName 传过来的任务名称
         * @param time             更新后的时间规则
         */
        public void modifyJobTime(String triggerName, String triggerGroupName, String time) {
            try {
                TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);    //通过触发器名和组名获取TriggerKey
                CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);                //通过TriggerKey获取CronTrigger
                if (trigger == null) return;
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(trigger.getCronExpression());
                String oldTime = trigger.getCronExpression();
                if (!oldTime.equalsIgnoreCase(time)) {
                    trigger = (CronTrigger) trigger.getTriggerBuilder()        //重新构建trigger
                            .withIdentity(triggerKey)
                            .withSchedule(scheduleBuilder)
                            .withSchedule(CronScheduleBuilder.cronSchedule(time))
                            .build();
                    scheduler.rescheduleJob(triggerKey, trigger);                //按新的trigger重新设置job执行
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
    
        /**
         * 移除一个任务(使用默认的任务组名,触发器名,触发器组名)
         *
         * @param jobName  任务名称
         * @param jobGroup 任务组名
         */
        public void removeJob(String jobName, String jobGroup) {
            try {
                TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);    //通过触发器名和组名获取TriggerKey
                JobKey jobKey = JobKey.jobKey(jobName, jobGroup);                        //通过任务名和组名获取JobKey
                scheduler.pauseTrigger(triggerKey);    // 停止触发器
                scheduler.unscheduleJob(triggerKey);// 移除触发器
                scheduler.deleteJob(jobKey);        // 删除任务
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 移除一个任务
         *
         * @param jobName          任务名
         * @param jobGroupName     任务组名
         * @param triggerName      触发器名
         * @param triggerGroupName 触发器组名
         */
        public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
            try {
                TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);    //通过触发器名和组名获取TriggerKey
                JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);                            //通过任务名和组名获取JobKey
                scheduler.pauseTrigger(triggerKey);    // 停止触发器
                scheduler.unscheduleJob(triggerKey);// 移除触发器
                scheduler.deleteJob(jobKey);        // 删除任务
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 启动所有定时任务
         */
        public void startJobs() {
            try {
                scheduler.start();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 关闭所有定时任务
         */
        public void shutdownJobs() {
            try {
                if (!scheduler.isShutdown()) {
                    scheduler.shutdown();
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 获取Trigger
         *
         * @param jobName  任务名
         * @param jobGroup 任务组名
         * @return
         */
        public Trigger getTrigger(String jobName, String jobGroup) {
            try {
                TriggerKey key = TriggerKey.triggerKey(jobName, jobGroup);
                return scheduler.getTrigger(key);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
        /**
         * 暂停任务
         *
         * @param jobName
         * @param jobGroup
         */
        public void pauseJob(String jobName, String jobGroup) {
            try {
                JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
                scheduler.pauseJob(jobKey);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 恢复任务
         *
         * @param jobName
         * @param jobGroup
         */
        public void resumeJob(String jobName, String jobGroup) {
            try {
                JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
                scheduler.resumeJob(jobKey);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 运行一次
         *
         * @param jobName
         * @param jobGroup
         * @param cls
         * @param param
         */
        public void runone(String jobName, String jobGroup, Class<? extends Job> cls, Map<String, Object> param) {
            JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, jobGroup).build();
            jobDetail.getJobDataMap().putAll(param);
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup).startNow().build();
            try {
                if (scheduler.checkExists(trigger.getKey())) {
                    throw new RuntimeException("任务正在执行请不要重复操作!");
                }
                scheduler.scheduleJob(jobDetail, trigger);
                ;
            } catch (SchedulerException e) {
                e.printStackTrace();
    
            }
    
        }
    }
    

    感谢参考:[https://blog.csdn.net/qq_42235671/article/details/84642721
    ]

    相关文章

      网友评论

          本文标题:定时任务

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