定时任务

2020-05-22  本文已影响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
]

上一篇下一篇

猜你喜欢

热点阅读